1 //-----------------------------------------------------------------------------
2 // example.vpl created 2018-01-19 10:01
3 //-----------------------------------------------------------------------------
8 // Input variables that can be configured via the configuration dialog (These are global)
12 // Output variables that can be configured via the configuration dialog (These are global)
15 AOUT : ARRAY[1 .. 4] OF INT; | Analog output
18 //-----------------------------------------------------------------------------
20 //-----------------------------------------------------------------------------
21 FUNCTION DataToHex : STRING;
26 reverse : BOOL := FALSE;
38 FOR i := 0 TO (datasize-1) DO
39 // Copy contents of one memory area to another area
40 memcpy(dst:=ADDR(src), src:=(data + i), len:=1);
43 v := SINT(src AND 16#0F);
44 src := shr8(in := src, n := 4);
46 0..9: bstr := intToStr(v := v) + bstr;
47 10 : bstr := "A" + bstr;
48 11 : bstr := "B" + bstr;
49 12 : bstr := "C" + bstr;
50 13 : bstr := "D" + bstr;
51 14 : bstr := "E" + bstr;
52 15 : bstr := "F" + bstr;
55 str_len := str_len + 1;
56 IF (str_len >= 254) THEN
61 DataToHex := DataToHex + bstr;
63 DataToHex := bstr + DataToHex;
68 WHILE ((str_len < 254) AND (str_len < length)) DO
70 DataToHex := DataToHex + "0";
72 DataToHex := "0" + DataToHex;
74 str_len := str_len + 1;
78 //-----------------------------------------------------------------------------
80 //-----------------------------------------------------------------------------
81 FUNCTION dintToHex2 : STRING;
85 reverse : BOOL := FALSE;
87 dintToHex2 := DataToHex(data := ADDR(v), datasize:= SIZEOF(v), length := length, reverse := reverse);
90 //-----------------------------------------------------------------------------
92 //-----------------------------------------------------------------------------
93 FUNCTION intToHex2 : STRING;
97 reverse : BOOL := FALSE;
99 intToHex2 := DataToHex(data := ADDR(v), datasize:= SIZEOF(v), length := length, reverse := reverse);
102 //-----------------------------------------------------------------------------
104 //-----------------------------------------------------------------------------
105 FUNCTION sintToHex2 : STRING;
109 reverse : BOOL := FALSE;
111 sintToHex2 := DataToHex(data := ADDR(v), datasize:= SIZEOF(v), length := length, reverse := reverse);
114 //-----------------------------------------------------------------------------
115 // Converts the raw value to a string with the voltage
116 //-----------------------------------------------------------------------------
117 FUNCTION convData:STRING;
125 // Copy raw value to DINT
126 memcpy(src:=data, dst:=ADDR(val), len:=3);
127 // convert raw value to voltage.
128 v := FLOAT(val) * 2.048*337.3/(exp2(v:=20.0)*67.3);
129 convData := strLeft(str:=floatToStr(v:=v), length := 5)+" V";
132 //-----------------------------------------------------------------------------
133 // Get the three-letter manufaturer code from the raw number
134 //-----------------------------------------------------------------------------
135 FUNCTION convMan : STRING;
141 data:ARRAY[1..3] OF SINT;
143 data[1] := sinT(((man/(32*32))MOD 32)+64);
144 data[2] := sinT(((man/(32))MOD 32)+64);
145 data[3] := sinT(((man)MOD 32)+64);
147 convMan := strFromMemory(src:=ADDR(data), len := 3);
150 //-----------------------------------------------------------------------------
151 // Parse the ADC data and print the individual fields to the output.
152 //-----------------------------------------------------------------------------
162 memcpy (src:=data+5, dst:=ADDR(enc),len:=2);
164 DebugFmt(message := "ADC"
165 + ", A# " +DataToHex(data := data+1, datasize := 1, length := 2)
166 + ", St " +DataToHex(data := data+2, datasize := 1, length := 2)
167 + ", Sig " +DataToHex(data := data+3, datasize := 2, length := 4)
168 + ", enc " +intToHex2(v:=enc)
170 IF enc = 16#2f2f THEN
171 // Data is valid, print it
172 DebugFmt(message:="Data Type: "+DataToHex(data := data+7, datasize := 1, length := 2)
173 +", pVIF: "+DataToHex(data := data+8, datasize := 1, length := 2)
174 +", sVIF: "+DataToHex(data := data+9, datasize := 1, length := 2)
175 +", Value: "+DataToHex(data := data+10, datasize := 3, length := 6)
177 DebugFmt(message:="Val: "+convData(data:=data+10));
182 //-----------------------------------------------------------------------------
183 // Parse the ADC log data and print the individual fields to the output.
184 //-----------------------------------------------------------------------------
194 memcpy (src:=data+6, dst:=ADDR(enc),len:=2);
196 DebugFmt(message := "Log: "
197 + "Func "+DataToHex(data := data+1, datasize := 1, length := 2)
198 + ", A# " + DataToHex(data := data+2, datasize := 1, length := 2)
199 + ", St " + DataToHex(data := data+3, datasize := 1, length := 2)
200 + ", Sig " +DataToHex(data := data+4, datasize := 2, length := 4)
201 + ", enc " +intToHex2(v:=enc)
204 IF enc = 16#2f2f THEN
205 DebugFmt(message:="His Type: "+DataToHex(data := data+8, datasize := 1, length := 2)
206 +", pVIF: "+DataToHex(data := data+9, datasize := 1, length := 2)
207 +", sVIF: "+DataToHex(data := data+10, datasize := 1, length := 2)
208 +", ValT: "+DataToHex(data := data+11, datasize := 1, length := 2)
209 +", Smpl: "+DataToHex(data := data+12, datasize := 3, length := 6)
213 "His#: "+DataToHex(data := data+15, datasize := 1, length := 2)
214 +", Time: "+DataToHex(data := data+16, datasize := 3, length := 6)
215 +", Part: "+DataToHex(data := data+19, datasize := 1, length := 2)
216 +", Vals: "+DataToHex(data := data+20, datasize := 1, length := 2)
218 memcpy(src := data+20, dst := ADDR(vals), len := 1);
219 DebugFmt(message:="vals: \1, "+DataToHex(data := ADDR(vals), datasize := 1, length := 2), v1:=vals);
220 for i := 0 to vals-1 DO
222 " [\1]: "+DataToHex(data := data+21+i*6, datasize := 3, length :=6)
223 +", "+DataToHex(data := data+24+i*6, datasize := 3, length :=6)
224 +", "+convData(data:=data+24+i*6)
232 //-----------------------------------------------------------------------------
233 // The RTCU Application
234 //-----------------------------------------------------------------------------
237 sms : gsmIncomingSMS;
241 path : STRING := MBUS_MODULE_PATH;
242 media : SINT := MBUS_MODULE_MEDIA;
253 key : ARRAY [1..16] OF SINT;
254 error_count : INT := 0;
256 Sleep(delay := 1000);
257 DebugMsg(message := "booting");
259 pre := strFormat(format := "MBUS(\1): ", v1 := thGetID());
260 DebugFmt(message := pre + "Started");
265 DebugFmt(message := pre + "init = \1", v1 := rc);
266 DebugMsg(message := "Extension: " + path);
267 FOR index := 1 TO 10 DO
268 // Read the name of a tag
269 rc:=extTagEnumerate(path:=path, index:=index, tag:=tag);
271 // Read the text of a tag
272 rc := extTagRead(path:=path,tag:=tag,text:=text);
274 DebugFmt(message := "[\1] : '" + strLeft(str := tag + "' ", length := 13) + "= '" + text + "'", v1 := index);
280 DebugMsg(message := "Failed to show tags.");
285 DebugMsg(message := "ready");
287 // Encryption key. It is normally unique for each slave.
307 IF (sms.status > 0) THEN
308 DebugMsg(message := "SMS: '"+sms.message+"'");
309 FOR index := 1 TO 10 DO
310 // Extract a string from another delimited string
311 cmd := strToken(str:=sms.message, delimiter:=";", index:=index);
312 //DebugMsg(message := "cmd = '"+cmd+"'");
315 ELSIF (cmd = "start") THEN
316 rc := mbusOpen(mode := MBUS_MODE_T1, RSSI:=ON, max_frames:=100, overwrite:=ON);
317 DebugFmt(message := "MBUS: open = \1", v1 := rc);
319 ELSIF (cmd = "stop") THEN
321 DebugFmt(message := "MBUS: close = \1", v1 := rc);
323 ELSIF (cmd = "lvl") THEN
324 rc := mbusGetBufferLevel();
325 DebugFmt(message := "MBUS: buffer level = \1", v1 := rc);
327 ELSIF (cmd = "read") THEN
328 rc := mbusReceive(frame:=frame, type:=16#ff, timeout:=120000 );
330 DebugFmt(message := pre + "failed to to fetch data (err \1)", v1 := rc);
331 error_count := error_count +1;
334 DebugFmt(message := "Man : "+ convMan(man:=frame.manufacturer)+" (" + intToHex2(v:=frame.manufacturer, reverse := false) + ")");
335 DebugFmt(message := "Received at: linsec \4", v4:=frame.linsec);
336 DebugFmt(message:="Length: \1, RSSI: \2 ("+floatToStr(v:=-FLOAT(frame.rssi) / 2.0)+" dB)", v1:=frame.length, v2:=frame.rssi);
338 16#19: type := "ADC"; // AD Converter
340 type := "0x" + DataToHex(data := ADDR(frame.type), datasize := SIZEOF(frame.type), length := 2);
342 DebugFmt(message := type + " : " + dintToHex2(v:=frame.id, reverse := false) + " => " +
343 DataToHex(data := ADDR(frame.data), datasize := frame.length, reverse := true));
344 if frame.type = 16#19 THEN
345 memcpy(dst:=ADDR(ci), src := ADDR(frame.data), len := 1);
347 " CI-field: " + DataToHex(data := ADDR(ci), datasize := 1, length := 2));
349 122://16#7A as decimal
350 ParseADC(data := ADDR(frame.data));
352 -83://16#AD as decimal
353 ParseLog(data := ADDR(frame.data));
355 DebugFmt(message:="Unknown message");
359 DebugFmt(Message:="No elements in buffer");
362 ELSIF (cmd = "send") THEN
363 index := INT(random(lower := -32768, upper := 32767));
364 rc := mbusSend(control := 16#44, data := ADDR(index), length := SIZEOF(index));
365 DebugFmt(message := "MBUS: send '" + intToHex2(v:=index) + "'= \1", v1 := rc);
367 ELSIF (cmd = "ack") THEN
368 rc := mbusSend(control := 0, length := 0);
369 DebugFmt(message := "MBUS: ack = \1", v1 := rc);
371 ELSIF (cmd = "info") THEN
373 DebugFmt(message := "MBUS: info = \1", v1 := rc);
375 ELSIF (cmd = "reset") THEN
376 DebugMsg(message := "resetting");
378 ELSIF (cmd = "reg") THEN
379 DebugMsg(message := "register sensors");
381 rc := mbusRegisterSlave(idx := 1, manufacturer:=16#0646, id:=16#10000530, version:=1, type := 16#19, key := ADDR(key));
382 DebugFmt(message := "MBUS: reg = \1", v1 := rc);
384 rc := mbusRegisterSlave(idx := 2, manufacturer:=16#0646, id:=16#20000530, version:=1, type := 16#19, key := ADDR(key));
385 DebugFmt(message := "MBUS: reg = \1", v1 := rc);
387 ELSIF (cmd = "AOUT[2]") THEN
388 AOUT[2] := AOUT[2] + (1023/4);
389 IF (AOUT[2] > 1023) THEN AOUT[2] := 0; END_IF;
391 ELSIF (cmd = "AOUT[1]") THEN
392 AOUT[1] := AOUT[1] + (1023/4);
393 IF (AOUT[1] > 1023) THEN AOUT[1] := 0; END_IF;
399 DebugMsg(message := "stopped");