...
- Create a new Project in TQLStudio by importing content from Baseline models.
Pipeline Macros
Code Block |
---|
language | xml |
---|
title | Greenhouse DataModel and TypesPipeline Macros |
---|
linenumbers | true |
---|
|
<Def<Macro Name="EnvInfoexecuteQuery">
<Argument>
<Number Name="Temperature"/> <QueryString>
<Number Name="Humidity"<Query/>
</QueryString>
<Number Name="Light"/>
</Argument>
<Result>
<Number Name="Pressure"/<OnRequest Target="[:RuntimeParams.FacetIDName:]" Disable="CMD_SERVER">
<Number<Process NameReturn="SoilMoistureCMD_NOP"/>
<Number Name="Wind"/> <Message>
<String Name="LastUpdatedByProvider"/>
</Def>
<Def Name="BoundingBox <Value>
[:$Macro.Argument.QueryString:]
</Value>
</Message>
</Process>
</OnRequest>
</Result>
</Macro> |
Main CreateGreenhouse Macro
Code Block |
---|
language | xml |
---|
title | Main Create Greenhouse Macro |
---|
linenumbers | true |
---|
|
<Macro Name="CreateGreenhouse">
<Argument>
<Greenhouses></Greenhouses>
</Argument>
<Result>
<SetLocalData key="Greenhouses">
<Value>
<Include>$Macro.Argument.Greenhouses</Include>
</Value>
</SetLocalData>
<for each="record" in="Greenhouse" from="$LocalData.Greenhouses" using="$ProcessData">
<JavaScript>
var NumberOfLanes = [:$ProcessData.record.NumberOfLanes:];
var ZonesPerLane = [:$ProcessData.record.ZonesPerLane:];
var NumberOfZones = NumberOfLanes * ZonesPerLane;
sffContext.execute("SetLocalData","key","NumberOfZones","value",NumberOfZones);
</JavaScript>
<executeQuery>
<QueryString>
<Query>
<Create>
<Greenhouse>
<GreenhouseName>[:$ProcessData.record.GreenHouseName:]</GreenhouseName>
<BoundingBox>
<Vertex1>0</Vertex1>
<Vertex2>0</Vertex2>
<Vertex3>110</Vertex3>
<Vertex4>40</Vertex4>
</BoundingBox>
<LaneCount>
[:$ProcessData.record.NumberOfLanes:]
</LaneCount>
<LaneWidth>110</LaneWidth>
<ZoneLength>10</ZoneLength>
<ZoneInLane>
[:$ProcessData.record.ZonesPerLane:]
</ZoneInLane>
<ZoneCount>[:$LocalData.NumberOfZones:]</ZoneCount>
<GHLength>110</GHLength>
<GHWidth>40</GHWidth>
<ExternalEnv>
<Temperature>1</Temperature>
<Humidity>1</Humidity>
<Light>1</Light>
<SoilMoisture>1</SoilMoisture>
<Wind>19.5</Wind>
</ExternalEnv>
<InternalEnv>
<Temperature>1</Temperature>
<Humidity>1</Humidity>
<Light>1</Light>
<SoilMoisture>1</SoilMoisture>
</InternalEnv>
<GHLanes></GHLanes>
<SunnyDay>True</SunnyDay>
<Location>
<latitude> [:$ProcessData.record.Location.latitude:] </latitude>
<longitude> [:$ProcessData.record.Location.longitude:] </longitude>
</Location>
</Greenhouse>
</Create>
</Query>
</QueryString>
</executeQuery>
<if condition="$Response.Message.Value/Create/Status eq 'Success'">
<then>
<SetContextData key="GreenhouseID">
<Value>[:$Response.Message.Value.Create.Greenhouse.GreenhouseID:]</Value>
</SetContextData>
<executeQuery>
<QueryString>
<Query>
<Save format="version,current">
<ExtTempSensor>
<peripheral>
serial
</peripheral>
<baudrate>
115200
</baudrate>
<interfacePort>
/dev/cu.usbserial-AH02V4BU
</interfacePort>
<interface>
serial
</interface>
<format>
ascii
</format>
<operation>
receive
</operation>
<uniqueId>
76522
</uniqueId>
<avgMonthHighTemp>
</avgMonthHighTemp>
<avgMonthLowTemp>
</avgMonthLowTemp>
<TempValue>
</TempValue>
<SensingInterval>
3600
</SensingInterval>
</ExtTempSensor>
</Save>
<Save format="version,current">
<ExtHumiditySensor>
<peripheral>
serial
</peripheral>
<baudrate>
115200
</baudrate>
<interfacePort>
/dev/cu.usbserial-AH02V4BU
</interfacePort>
<interface>
serial
</interface>
<format>
ascii
</format>
<operation>
receive
</operation>
<uniqueId>
76522
</uniqueId>
<avgMonthHighTemp>
</avgMonthHighTemp>
<avgMonthLowTemp>
</avgMonthLowTemp>
<HumidityValue>
</HumidityValue>
</ExtHumiditySensor>
</Save>
<Save format="version,current">
<GeoLocation Name="Vertex1"/> <GeoLocation Name="Vertex2"/> <ExtLightSensor>
<GeoLocation Name="Vertex3"/> <GeoLocation Name="Vertex4"/> </Def> <peripheral>
<Def
Name="GeoLocation"> <Number Name="latitude"/> <Number Name="longitude"/> </Def> serial
<DataModel Name="Greenhouse"> <Sid Name="GreenhouseID"/> <String Name="GreenhouseName"/></peripheral>
<GeoLocation Name="Location"/> <String Name="LocationName"/> <baudrate>
<BoundingBox Name="Boundary"/> <Integer Name="LaneCount"/> <Double Name="LaneWidth"/> 115200
<Double Name="ZoneLength"/> <Integer Name="ZoneInLane"/> <Integer Name="ZoneCount"/> </baudrate>
<Double Name="GHLength"/> <Double Name="GHWidth"/> <interfacePort>
<EnvInfo Name="ExternalEnv"/> <EnvInfo Name="InternalEnv"/> <String Name="VentOnOffState"/> /dev/cu.usbserial-AH02V4BU
<String Name="FansOnOffState"/> <Boolean Name="SunnyDay"/> <Boolean Name="Running" default="false"/> <!-- true / false -->/interfacePort>
</DataModel> <ThingModel Name="Heater"> <Sid Name="HeaterID"/><interface>
<String Name="OnOffState"/> <Integer Name="HeatingLevel"/> </ThingModel> |
Pipeline Macros
- Execute Internal Query
- Schedule and UnSchedule TQL Code
Code Block |
---|
language | xml |
---|
title | Pipeline Macros |
---|
linenumbers | true |
---|
|
<Macro Name="executeQuery"> serial
<Argument> <QueryString> <Query/> </QueryString> </Argument>interface>
<Result> <OnRequest Target="[:RuntimeParams.FacetIDName:]" Disable="CMD_SERVER"> <Process Return="CMD_NOP"> <format>
<Message> <Value> ascii
[:$Macro.Argument.QueryString:] </Value>
</Message>format>
</Process> </OnRequest> </Result> </Macro> <Macro Name="DeleteScheduleJob"> <operation>
<Argument>
<JobName/> </Argument> <Result> <DoRequest target="[:RuntimeParams.SequenceFacetIDName:]"> receive
<Process> <Message type="xml"> </operation>
<Value>
<Remove eid="[:$Macro.Argument.JobName:]"/> <uniqueId>
</Value> </Message> </Process> 76522
</DoRequest>
</Result> </Macro> <Macro Name="ScheduleJob"> <Argument> <ScheduleInterval> </ScheduleInterval>uniqueId>
<StartTime> 0 </StartTime> <Intensity>
<EndTime> </EndTime> <ActionCode> </ActionCode> <Name> $Null()
</Name> </Argument> <Result> <Log Message="Inside ScheduleJob macro"/> </Intensity>
<DoRequest
target="[:RuntimeParams.SequenceFacetIDName:]"> <Process> <Message> <HourMeanLight>
<Value> <Execute eid="[:$Macro.Argument.Name:]" schedule="[[:$Macro.Argument.StartTime:]..[:$Macro.Argument.EndTime:]/[:$Macro.Argument.ScheduleInterval:]]"> </HourMeanLight>
<Action> <LightValue>
<ExecuteQuery> </LightValue>
<QueryString> </ExtLightSensor>
[:$Macro.Argument.ActionCode:] </Save>
</QueryString> <Save format="version,current">
</ExecuteQuery> <GHTempSensor>
</Action> </Execute> <GreenhouseID>
</Value> </Message> </Process> </DoRequest>
</Result>
</Macro> |
Macro to Simulate Sensor
Code Block |
---|
language | xml |
---|
title | Simulate Sensor Logic |
---|
linenumbers | true |
---|
|
<Macro Name="SetGHCurrentTemp">[:$ContextData.GreenhouseID:]
<Argument> <TempSensorId><</TempSensorId>GreenhouseID>
<GreenhouseID></GreenhouseID> </Argument> <peripheral>
<Result>
<Log Message="*********Calculating Temperature..."/> <executeQuery> serial
<QueryString> <Query> </peripheral>
<Find> <baudrate>
<Greenhouse> 115200
<GreenhouseID>[:$Macro.Argument.GreenhouseID:]</GreenhouseID> </Greenhouse>baudrate>
<interfacePort>
</Find> </Query> /dev/cu.usbserial-AH02V4BU
</QueryString> </executeQuery> <if condition="$Response.Message.Value/Find/Status eq 'Success'"> </interfacePort>
<then> <interface>
<SetLocalData key="CurrentTemp"> <Value>[:$Response.Message.Value.Find.Result.Greenhouse.ExternalEnv.Temperature:]</Value> serial
</SetLocalData> </interface>
<SetLocalData key="GHCurrentTemp"> <Value>[:$Response.Message.Value.Find.Result.Greenhouse.InternalEnv.Temperature:]</Value> <format>
</SetLocalData> ascii
<SetLocalData key="Vent"> <Value>[:$Response.Message.Value.Find.Result.Greenhouse.VentOnOffState:]</Value>format>
</SetLocalData> <operation>
<SetLocalData key="Fans"> <Value>[:$Response.Message.Value.Find.Result.Greenhouse.FansOnOffState:]</Value>
receive
</SetLocalData> </operation>
<SetLocalData key="SunnyDay"> <Value>[:$Response.Message.Value.Find.Result.Greenhouse.SunnyDay:]</Value><uniqueId>
</SetLocalData> 76522
<executeQuery> <QueryString> </uniqueId>
<Query> <avgMonthHighTemp>
<Find> </avgMonthHighTemp>
<Heater> <avgMonthLowTemp>
<OnOffState eq='On'/> </avgMonthLowTemp>
</Heater> <TempValue>
</Find> </TempValue>
</Query> <SensingInterval>
</QueryString> </executeQuery> 3600
<Javascript> </SensingInterval>
<resp> <Include>$Response.Message.Value</Include></GHTempSensor>
</resp>Save>
var resultList<Save format= resp.Find;"version,current">
<GHHumiditySensor>
var heaterLevels = []; var<GreenhouseID>
heaterLevelsSum = 0; for each (var result in resultList.iterEntries("Result")){[:$ContextData.GreenhouseID:]
var heaters = </GreenhouseID>
result.getValue(); <peripheral>
heaterLevels.push(heaters.Heater.HeatingLevel); heaterLevelsSum = heaterLevelsSum + heaters.Heater.HeatingLevel; serial
} </peripheral>
var GHTempAdj = <baudrate>
0; if([:$LocalData.SunnyDay:]){
115200
GHTempAdj = Math.pow((100/([:$LocalData.CurrentTemp:]+237.1)), 3) * 100; </baudrate>
}else{ <interfacePort>
GHTempAdj = Math.pow((100/([:$LocalData.CurrentTemp:]+237.1)), 3) * 60;/dev/cu.usbserial-AH02V4BU
}</interfacePort>
var GHBaseTemp = [:$LocalData.CurrentTemp:] + GHTempAdj;<interface>
var TempVentImp = serial
([:$LocalData.CurrentTemp:] - [:$LocalData.GHCurrentTemp:]) * 0.03; </interface>
var HeaterEffectRatio = heaterLevelsSum / 90; <format>
var TempHeaterImp = ascii
HeaterEffectRatio * (Math.sqrt(Math.max(0,(45-[:$LocalData.GHCurrentTemp:])))); </format>
var GHCurrentTemp = GHBaseTemp + TempVentImp + TempHeaterImp; <operation>
sffContext.execute("SetContextData","key","GHCurrentTemp","value",GHCurrentTemp); </Javascript> receive
<executeQuery> </operation>
<QueryString> <uniqueId>
<Query> <Find format="Version"> 76522
<TempSensor> </uniqueId>
<sensorId>[:$Macro.Argument.TempSensorId:]</sensorId><HumidityValue>
</TempSensor> 0
</Find> </HumidityValue>
<SetResponseData> </GHHumiditySensor>
<Key>Message.Value.Find.Result.TempSensor.TempValue.Value</Key></Save>
</Query>
<Value>[:$ContextData.GHCurrentTemp:]</Value> </QueryString>
</SetResponseData>executeQuery>
<SetContextData key="FirstLane">
<Save> <Value>Yes</Value>
</SetContextData>
<from>Result</from> <For each="laneRecord" in="Lane" from="$ProcessData.record.Lanes" using="$LocalData">
<Include>$Response.Message.Value.Find</Include> <addLanes>
<GreenhouseID>[:$ContextData.GreenhouseID:]</Save>GreenhouseID>
<LaneName>[:$LocalData.laneRecord.LaneName:]</Query>LaneName>
<<LaneLength>110</QueryString>LaneLength>
</executeQuery> <LaneWidth>40</LaneWidth>
<executeQuery> <ZoneInLane>[:$ProcessData.record.ZonesPerLane:]</ZoneInLane>
<QueryString> <BorderLane>No</BorderLane>
</addLanes>
<Query> <Find format="Version">
<if condition="$Response.Message.Value/Create/Status eq 'Success'">
<Greenhouse> <then>
<SetLocalData key="LaneID">
<GreenhouseID>[:$Macro.Argument.GreenhouseID:]</GreenhouseID> </Greenhouse>
<Value>[:$Response.Message.Value.Create.Lane.LaneID:]</Value>
</Find>SetLocalData>
<loadZoneModels>
<SetResponseData> <Key>Message.Value.Find.Result.Greenhouse.InternalEnv.Temperature.Value</Key>
<LaneID>[:$LocalData.LaneID:]</LaneID>
<Value><ZonesPerLane>[:$ContextData$ProcessData.record.GHCurrentTempZonesPerLane:]</Value>ZonesPerLane>
<CropType>[:$LocalData.laneRecord.CropType:]</SetResponseData>CropType>
<Save><FirstLane>[:$ContextData.FirstLane:]</FirstLane>
<from>Result</from></loadZoneModels>
</then>
<Include>$Response.Message.Value.Find</Include> </if>
</Save> <SetContextData key="FirstLane">
<<Value>No</Query>
Value>
</QueryString>SetContextData>
</executeQuery>
For>
</then>
</if>
</for>
</Result>
</Macro> |
Add Action to Start Simulate
...