Last active
July 23, 2025 15:31
-
-
Save TobeTek/3d82e3860a266ec4b185f855fa95ff13 to your computer and use it in GitHub Desktop.
Soil Health Advisor - MATLAB App - Get AI powered advice on how to manage your farm for your crops
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| classdef app1_exported < matlab.apps.AppBase | |
| % Properties that correspond to app components | |
| properties (Access = public) | |
| UIFigure matlab.ui.Figure | |
| GetAIpoweredinsightsforyourfarmLabel matlab.ui.control.Label | |
| SoilHealthAdvisorLabel matlab.ui.control.Label | |
| StatusIdleLabel matlab.ui.control.Label | |
| TipsTextArea matlab.ui.control.TextArea | |
| TipsTextAreaLabel matlab.ui.control.Label | |
| GetTipsButton matlab.ui.control.Button | |
| CropTypeEditField matlab.ui.control.EditField | |
| CropTypeEditFieldLabel matlab.ui.control.Label | |
| FarmFieldLocationEditField matlab.ui.control.EditField | |
| FarmFieldLocationEditFieldLabel matlab.ui.control.Label | |
| DepthValue0Label matlab.ui.control.Label | |
| DepthofSoilTextureMeasurementcmSlider matlab.ui.control.Slider | |
| DepthofSoilTextureMeasurementcmSliderLabel matlab.ui.control.Label | |
| SoilTextureDropDown matlab.ui.control.DropDown | |
| SoilTextureDropDownLabel matlab.ui.control.Label | |
| end | |
| % Internal soil texture data | |
| properties (Access = private) | |
| SoilTextureData % Table of texture classes and colors | |
| end | |
| methods (Access = private) | |
| function setupSoilTextures(app) | |
| app.SoilTextureData = table( ... | |
| {'Sand'; 'Loamy Sand'; 'Sandy Loam'; 'Loam'; 'Silt Loam'; 'Clay Loam'; 'Clay'}, ... | |
| {'#F4D35E'; '#F7B32B'; '#FAA916'; '#90BE6D'; '#43AA8B'; '#577590'; '#2F4858'}, ... | |
| 'VariableNames', {'Name', 'Color'}); | |
| app.SoilTextureDropDown.Items = app.SoilTextureData.Name'; | |
| % Each item colored accordingly (MATLAB dropdown does not support item coloring by default, | |
| % so just set dropdown background color to selected color on value change: | |
| app.SoilTextureDropDown.BackgroundColor = '#FFFFFF'; % default white | |
| end | |
| function updateDepthValueLabel(app) | |
| val = round(app.DepthofSoilTextureMeasurementcmSlider.Value); | |
| app.DepthValue0Label.Text = sprintf('%d cm', val); | |
| end | |
| function updateDropdownColor(app) | |
| % Change dropdown background color to selected soil texture color (approximate UI feedback) | |
| idx = find(strcmp(app.SoilTextureDropDown.Value, app.SoilTextureData.Name)); | |
| if ~isempty(idx) | |
| color = app.SoilTextureData.Color{idx}; | |
| app.SoilTextureDropDown.BackgroundColor = color; | |
| end | |
| end | |
| function onDropdownChanged(app, ~) | |
| app.updateDropdownColor(); | |
| end | |
| function onDepthSliderChanged(app, ~) | |
| app.updateDepthValueLabel(); | |
| end | |
| function fetchAndDisplayAITips(app) | |
| % Collect user data | |
| texture = app.SoilTextureDropDown.Value; | |
| depth = round(app.DepthofSoilTextureMeasurementcmSlider.Value); | |
| fieldName = app.FarmFieldLocationEditField.Value; | |
| cropType = app.CropTypeEditField.Value; | |
| if isempty(texture) | |
| uialert(app.UIFigure,'Please select a soil texture class.','Input Required'); | |
| return | |
| end | |
| % Create prompt for AI assistance | |
| prompt = sprintf(['I am a farmer with soil texture "%s" at %d cm depth. ', ... | |
| 'My field is called "%s" and I am growing "%s". ', ... | |
| 'Please provide practical tips to improve crop yield and soil health. Format without markdown (plain text). Keep response brief (1 paragraph) and useful and natural sounding. Offer next steps on things I the farmer should do'], ... | |
| texture, depth, fieldName, cropType); | |
| app.StatusIdleLabel.Text = 'Contacting AI service... please wait.'; | |
| drawnow; | |
| % HuggingFace inference API public endpoint URL | |
| api_url = 'https://api.groq.com/openai/v1/chat/completions'; | |
| api_token = '<REDACTED>'; | |
| requestBody = struct( ... | |
| 'model', 'llama-3.3-70b-versatile', ... | |
| 'messages', {{struct( ... | |
| 'role', 'user', ... | |
| 'content', prompt ... | |
| )}} ... | |
| ); | |
| % Setup web options without API key, JSON content type, 30s timeout | |
| options = weboptions('MediaType','application/json', ... | |
| 'Timeout',30, ... | |
| 'HeaderFields', {'Authorization', ['Bearer ' api_token]} ... | |
| ); | |
| try | |
| response = webwrite(api_url, requestBody, options); | |
| % Extract answer text | |
| if isstruct(response) && isfield(response, 'choices') && ~isempty(response.choices) | |
| if isfield(response.choices(1), 'message') && isfield(response.choices(1).message, 'content') | |
| ai_advice = response.choices(1).message.content; | |
| else | |
| ai_advice = 'AI response message content not found.'; | |
| end | |
| else | |
| ai_advice = 'AI response choices not found or empty.'; | |
| end | |
| catch ME | |
| ai_advice = sprintf('Error calling AI service:\n%s', ME.message); | |
| end | |
| % Display or use ai_advice | |
| app.TipsTextArea.Value = ai_advice; | |
| app.StatusIdleLabel.Text = 'AI tips updated.'; | |
| end | |
| end | |
| % Callbacks that handle component events | |
| methods (Access = private) | |
| % Code that executes after component creation | |
| function startupFcn(app) | |
| setupSoilTextures(app); | |
| end | |
| % Button pushed function: GetTipsButton | |
| function GetTipsButtonPushed(app, event) | |
| app.fetchAndDisplayAITips(); | |
| end | |
| % Value changed function: SoilTextureDropDown | |
| function SoilTextureDropDownValueChanged(app, event) | |
| % value = app.SoilTextureDropDown.Value; | |
| app.onDropdownChanged(); | |
| end | |
| % Value changed function: DepthofSoilTextureMeasurementcmSlider | |
| function DepthofSoilTextureMeasurementcmSliderValueChanged(app, event) | |
| % value = app.DepthofSoilTextureMeasurementcmSlider.Value; | |
| app.onDepthSliderChanged(); | |
| end | |
| end | |
| % Component initialization | |
| methods (Access = private) | |
| % Create UIFigure and components | |
| function createComponents(app) | |
| % Create UIFigure and hide until all components are created | |
| app.UIFigure = uifigure('Visible', 'off'); | |
| app.UIFigure.Color = [0.9176 0.9804 0.7843]; | |
| app.UIFigure.Position = [100 100 640 480]; | |
| app.UIFigure.Name = 'MATLAB App'; | |
| % Create SoilTextureDropDownLabel | |
| app.SoilTextureDropDownLabel = uilabel(app.UIFigure); | |
| app.SoilTextureDropDownLabel.HorizontalAlignment = 'right'; | |
| app.SoilTextureDropDownLabel.Position = [37 166 64 22]; | |
| app.SoilTextureDropDownLabel.Text = 'SoilTexture'; | |
| % Create SoilTextureDropDown | |
| app.SoilTextureDropDown = uidropdown(app.UIFigure); | |
| app.SoilTextureDropDown.ValueChangedFcn = createCallbackFcn(app, @SoilTextureDropDownValueChanged, true); | |
| app.SoilTextureDropDown.Position = [116 166 100 22]; | |
| % Create DepthofSoilTextureMeasurementcmSliderLabel | |
| app.DepthofSoilTextureMeasurementcmSliderLabel = uilabel(app.UIFigure); | |
| app.DepthofSoilTextureMeasurementcmSliderLabel.HorizontalAlignment = 'right'; | |
| app.DepthofSoilTextureMeasurementcmSliderLabel.WordWrap = 'on'; | |
| app.DepthofSoilTextureMeasurementcmSliderLabel.Position = [37 108 115 44]; | |
| app.DepthofSoilTextureMeasurementcmSliderLabel.Text = 'Depth of Soil Texture Measurement (cm)'; | |
| % Create DepthofSoilTextureMeasurementcmSlider | |
| app.DepthofSoilTextureMeasurementcmSlider = uislider(app.UIFigure); | |
| app.DepthofSoilTextureMeasurementcmSlider.ValueChangedFcn = createCallbackFcn(app, @DepthofSoilTextureMeasurementcmSliderValueChanged, true); | |
| app.DepthofSoilTextureMeasurementcmSlider.Position = [168 139 150 3]; | |
| % Create DepthValue0Label | |
| app.DepthValue0Label = uilabel(app.UIFigure); | |
| app.DepthValue0Label.FontAngle = 'italic'; | |
| app.DepthValue0Label.Position = [168 71 84 22]; | |
| app.DepthValue0Label.Text = 'Depth Value: 0'; | |
| % Create FarmFieldLocationEditFieldLabel | |
| app.FarmFieldLocationEditFieldLabel = uilabel(app.UIFigure); | |
| app.FarmFieldLocationEditFieldLabel.HorizontalAlignment = 'right'; | |
| app.FarmFieldLocationEditFieldLabel.Position = [31 217 111 22]; | |
| app.FarmFieldLocationEditFieldLabel.Text = 'Farm/Field Location'; | |
| % Create FarmFieldLocationEditField | |
| app.FarmFieldLocationEditField = uieditfield(app.UIFigure, 'text'); | |
| app.FarmFieldLocationEditField.Placeholder = 'City, country, landmarks, coordinates etc.'; | |
| app.FarmFieldLocationEditField.Position = [157 217 233 22]; | |
| % Create CropTypeEditFieldLabel | |
| app.CropTypeEditFieldLabel = uilabel(app.UIFigure); | |
| app.CropTypeEditFieldLabel.HorizontalAlignment = 'right'; | |
| app.CropTypeEditFieldLabel.Position = [31 268 60 22]; | |
| app.CropTypeEditFieldLabel.Text = 'Crop Type'; | |
| % Create CropTypeEditField | |
| app.CropTypeEditField = uieditfield(app.UIFigure, 'text'); | |
| app.CropTypeEditField.Placeholder = 'Corn, Beans etc. (Botanical names accepted as well)'; | |
| app.CropTypeEditField.Position = [106 268 301 22]; | |
| % Create GetTipsButton | |
| app.GetTipsButton = uibutton(app.UIFigure, 'push'); | |
| app.GetTipsButton.ButtonPushedFcn = createCallbackFcn(app, @GetTipsButtonPushed, true); | |
| app.GetTipsButton.BackgroundColor = [0.4 0.749 0.3373]; | |
| app.GetTipsButton.FontName = 'Trebuchet MS'; | |
| app.GetTipsButton.FontSize = 24; | |
| app.GetTipsButton.FontWeight = 'bold'; | |
| app.GetTipsButton.FontAngle = 'italic'; | |
| app.GetTipsButton.Position = [422 278 161 54]; | |
| app.GetTipsButton.Text = 'Get Tips!'; | |
| % Create TipsTextAreaLabel | |
| app.TipsTextAreaLabel = uilabel(app.UIFigure); | |
| app.TipsTextAreaLabel.HorizontalAlignment = 'right'; | |
| app.TipsTextAreaLabel.Position = [501 247 27 22]; | |
| app.TipsTextAreaLabel.Text = 'Tips'; | |
| % Create TipsTextArea | |
| app.TipsTextArea = uitextarea(app.UIFigure); | |
| app.TipsTextArea.Position = [422 22 185 217]; | |
| % Create StatusIdleLabel | |
| app.StatusIdleLabel = uilabel(app.UIFigure); | |
| app.StatusIdleLabel.FontAngle = 'italic'; | |
| app.StatusIdleLabel.Position = [215 355 238 22]; | |
| app.StatusIdleLabel.Text = 'Status: Idle'; | |
| % Create SoilHealthAdvisorLabel | |
| app.SoilHealthAdvisorLabel = uilabel(app.UIFigure); | |
| app.SoilHealthAdvisorLabel.FontName = 'Trebuchet MS'; | |
| app.SoilHealthAdvisorLabel.FontSize = 36; | |
| app.SoilHealthAdvisorLabel.Position = [148 421 372 48]; | |
| app.SoilHealthAdvisorLabel.Text = 'Soil Health Advisor 🌱'; | |
| % Create GetAIpoweredinsightsforyourfarmLabel | |
| app.GetAIpoweredinsightsforyourfarmLabel = uilabel(app.UIFigure); | |
| app.GetAIpoweredinsightsforyourfarmLabel.FontName = 'Trebuchet MS'; | |
| app.GetAIpoweredinsightsforyourfarmLabel.FontSize = 18; | |
| app.GetAIpoweredinsightsforyourfarmLabel.Position = [173 399 320 23]; | |
| app.GetAIpoweredinsightsforyourfarmLabel.Text = 'Get AI-powered insights for your farm!'; | |
| % Show the figure after all components are created | |
| app.UIFigure.Visible = 'on'; | |
| end | |
| end | |
| % App creation and deletion | |
| methods (Access = public) | |
| % Construct app | |
| function app = app1_exported | |
| % Create UIFigure and components | |
| createComponents(app) | |
| % Register the app with App Designer | |
| registerApp(app, app.UIFigure) | |
| % Execute the startup function | |
| runStartupFcn(app, @startupFcn) | |
| if nargout == 0 | |
| clear app | |
| end | |
| end | |
| % Code that executes before app deletion | |
| function delete(app) | |
| % Delete UIFigure when app is deleted | |
| delete(app.UIFigure) | |
| end | |
| end | |
| end |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Demo
chrome_haRZk6HfoT.mp4
This demo showcases a user-friendly application designed to optimize crop yield. Farmers simply input:
In return, they receive tailored advice and actionable recommendations aimed at maximizing their crop's productivity.
Behind the Scenes
At its core, the system leverages a MATLAB App built with App Designer. This application is pre-configured with a comprehensive knowledge base on various soil types.
It integrates with a prompt-tuned Large Language Model (LLM), accessed securely via the GROQ REST API. The LLM processes the farmer's input, combining it with the pre-existing soil data to generate precise, yield-improving insights.