1
(Pod)Systemy i Funkcje / Odczyt danych pogodowych ze stacji WH2600
« dnia: Września 04, 2015, 07:24:08 pm »
Witam
Chciałbym się podzielić swoim kodem do obsługi stacji pogodowej Renkforce WH2600 od Conrada http://www.conrad.pl/?websale8=conrad&pi=1267654&rdeocl=1&rdetpl=productpage&rdebox=box3
UWAGA: Należy gdzieś zdefiniowwać maksymalną dugość odpowiedzi TCP wpisując np w zmiennych globalnych:
Deklaracje:
Kod:
Funkcja (Makro?) SearchForString (nie mojego autorstwa):
Chciałbym się podzielić swoim kodem do obsługi stacji pogodowej Renkforce WH2600 od Conrada http://www.conrad.pl/?websale8=conrad&pi=1267654&rdeocl=1&rdetpl=productpage&rdebox=box3
UWAGA: Należy gdzieś zdefiniowwać maksymalną dugość odpowiedzi TCP wpisując np w zmiennych globalnych:
Kod: [Zaznacz]
MAX_RECEIVE_TCP_CLIENT: UINT := 12000;
Deklaracje:
Kod: [Zaznacz]
FUNCTION_BLOCK WH2600_weather
(*
Weather data from Renkforce WH2600 Weather Station (Weather Logger 1.1)
Based on pWorldWeatherForecast
31.05.2015 Marcin Rudzki
*)
VAR_INPUT
sAddress: STRING := '192.168.2.195';
END_VAR
VAR_OUTPUT
rInTemp: REAL := 0; (* Indoor temperature *)
iInHumi: INT := 0; (* Indoor humidity *)
rAbsPress: REAL := 0; (* Absolute pressure *)
rRelPress: REAL := 0; (* Relative pressure *)
rOutTempC: REAL := 0; (* Outdoor temperature *)
iOutHumi: INT:= 0; (* Outdoor humidity *)
iWinDir: INT := 0; (* Wind direction *)
sWinDir: STRING(3);
rAvgWind: REAL := 0; (* Average wind speed *)
rGustSpeed: REAL := 0; (* Gust speed *)
rSolarRad: REAL := 0; (* Solar radiation *)
iUV: INT := 0; (* UV *)
iUVI: INT := 0; (* UV index *)
rRainOfHourly: REAL := 0; (* Hourly Rain rate *)
rRainOfDaily: REAL := 0; (* Daily Rain Rate *)
rRainOfWeekly: REAL := 0; (* Weekly Rain Rate *)
rRainOfMonthly: REAL := 0; (* Monthly Rain Rate *)
rRainOfYearly: REAL := 0; (* Annually Rain Rate *)
sStatus: STRING;
diError: DINT;
END_VAR
VAR_IN_OUT
xStart : BOOL;
END_VAR
VAR
wStateMachine: WORD;
(* Function block HTTP_GET *)
oHTTP_GET:HTTP_GET;(* Input variables: *)
oHttp_sServerName : STRING ; (* Hostname or server IP in dotted normal form *)
oHttp_pabUrlData : POINTER TO ARRAY [0..MAX_RECEIVE_TCP_CLIENT] OF BYTE ; (* The HTTP-GET-Request *)
oHttp_uiUrlLength : UINT ; (* Length of HTTP-GET-Request *)
oHttp_tTimeOut : TIME := t#24s; (* WatchDogTime, operation aborted after time is elapsed *)
oHttp_xSend : BOOL ;
oHttp_diError : DINT ; (* 0 == successful *)
oHttp_sStatus : STRING(255) ;
oHttp_abContentData : ARRAY [0..MAX_RECEIVE_TCP_CLIENT] OF BYTE ; (* The HTTP response *)
oHttp_uiContentLength : UINT ; (* Length of HTTP response in byte *)
(* Function block HTTP_GET helper *)
sUrl: STRING(250);
sUrlHelp: STRING(250);
(* HTML file *)
abXmlFileStream : ARRAY [0..MAX_RECEIVE_TCP_CLIENT] OF BYTE ; (* The HTTP response *)
uiXmlFileStreamLen : UINT ; (* Length of HTTP response in byte *)
pabXmlHandler : POINTER TO ARRAY [0..MAX_RECEIVE_TCP_CLIENT] OF BYTE;
uiXmlHandlerIndex: UINT;
uiXmlStreamLen: UINT;
sSearchedString: STRING(105);
xFail: BOOL;
sHTTP_Response: STRING;
(* Helpers *)
i: INT;
uiPos: UINT;
bHelp: BYTE;
abHelp: ARRAY [0..50] OF BYTE;
psHelp: POINTER TO STRING(50);
sHelp: STRING(50);
xInSensorAbsent: BOOL := FALSE;
xOutSensorAbsent: BOOL := FALSE;
END_VAR
Kod:
Kod: [Zaznacz]
(* Function block HTTP_GET instance *)
oHTTP_GET (
(* Input variables: *)
sServerName := sAddress ,
wServerPort := 80 ,
pabUrlData := oHttp_pabUrlData,
uiUrlLength := oHttp_uiUrlLength,
tTimeOut := oHttp_tTimeOut,
(* Input/output variables: *)
xSend := oHttp_xSend,
(* Output variables: *)
diError => oHttp_diError,
sStatus => oHttp_sStatus,
abContentData => oHttp_abContentData ,
uiContentLength => oHttp_uiContentLength
);
CASE wStateMachine OF
0: (* Init *)
IF xStart THEN
(* Url builder *)
sUrl := '/livedata.htm';
(* Set HTTP_GET *)
oHttp_pabUrlData := ADR(sUrl);
oHttp_uiUrlLength := LEN(sUrl);
(* Process HTTP_GET *)
oHttp_xSend := TRUE;
wStateMachine := 10;
END_IF
10: (* Process the HTTP reguest *)
IF NOT oHttp_xSend THEN
IF oHttp_diError = 0 THEN
(* Process the weather HTML response *)
wStateMachine := 20;
ELSE
(* Error *)
sStatus := oHttp_sStatus;
diError := oHttp_diError;
wStateMachine := 999;
END_IF
END_IF
20: (* Process the weather HTML response *)
(* Get HTML stream *)
abXmlFileStream := oHttp_abContentData;
uiXmlFileStreamLen := oHttp_uiContentLength;
(* Set pointer to the start of the HTML file*)
uiXmlHandlerIndex := 0;
pabXmlHandler := ADR(abXmlFileStream[0]);
uiXmlStreamLen := uiXmlFileStreamLen;
sHTTP_Response := BUFFER_TO_STRING(pabXmlHandler,SIZEOF(abXmlFileStream),0,100);
(* Search for 'livedata' string in the HTML file *)
sSearchedString := 'form name="livedata" method="POST" onsubmit="return chkForm(0);"';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No livedata form in the stream!';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
wStateMachine := 25;
END_IF
25: (* Search for 'IndoorID' string in the HTML file *)
sSearchedString := 'input name="IndoorID" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="0x';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No indoorID in the stream';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
IF (psHelp^) = '--' THEN
sStatus := 'ERROR: No indoor sensor detected';
diError := 16#00000002;
xInSensorAbsent := TRUE;
ELSE
xInSensorAbsent := FALSE;
END_IF
wStateMachine := 27;
END_IF
27: (* Search for 'Outdoor1ID' string in the HTML file *)
sSearchedString := 'input name="Outdoor1ID" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="0x';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No Outdoor1ID in the stream';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
IF (psHelp^) = '--' THEN
sStatus := 'ERROR: No outdoor1 sensor detected';
IF xInSensorAbsent THEN
diError := 16#00000006;
wStateMachine := 999;
ELSE
diError := 16#00000004;
xOutSensorAbsent := TRUE;
wStateMachine := 30;
END_IF
ELSIF xInSensorAbsent THEN
xOutSensorAbsent := FALSE;
wStateMachine := 50;
ELSE
xOutSensorAbsent := FALSE;
wStateMachine :=30;
END_IF
END_IF
30: (* Search for 'inTemp' string in the HTML file *)
sSearchedString := 'input name="inTemp" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No inTemp in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rInTemp := STRING_TO_REAL(psHelp^);
wStateMachine := 40;
END_IF
40: (* Search for 'inHumi' string in the HTML file *)
sSearchedString := 'input name="inHumi" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No inTemp in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
iInHumi := STRING_TO_INT(psHelp^);
IF xOutSensorAbsent THEN
wStateMachine := 0;
xStart := FALSE;
ELSE
wStateMachine := 50;
END_IF
END_IF
50: (* Search for 'AbsPress' string in the HTML file *)
sSearchedString := 'input name="AbsPress" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No AbsPress in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rAbsPress := STRING_TO_REAL(psHelp^);
wStateMachine := 60;
END_IF
60: (* Search for 'RelPress' string in the HTML file *)
sSearchedString := 'input name="RelPress" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No RelPress in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rRelPress := STRING_TO_REAL(psHelp^);
(* *)
wStateMachine := 70;
END_IF
70: (* Search for 'outTemp' string in the HTML file *)
sSearchedString := 'input name="outTemp" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No outTemp in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rOutTempC := STRING_TO_REAL(psHelp^);
(* *)
wStateMachine := 80;
END_IF
80: (* Search for 'outHumi' string in the HTML file *)
sSearchedString := 'input name="outHumi" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No outHumi in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
iOutHumi := STRING_TO_INT(psHelp^);
(* *)
wStateMachine := 90;
END_IF
90: (* Search for 'windir' string in the HTML file *)
sSearchedString := 'input name="windir" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No windir in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
iWinDir := STRING_TO_INT(psHelp^);
sWinDir := AZIMUTH_TO_DIRECTION(iWinDir);
(* *)
wStateMachine := 100;
END_IF
100: (* Search for 'avg' string in the HTML file *)
sSearchedString := 'input name="avgwind" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No avgwind in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rAvgWind := STRING_TO_REAL(psHelp^);
(* *)
wStateMachine := 110;
END_IF
110: (* Search for 'gustspeed' string in the HTML file *)
sSearchedString := 'input name="gustspeed" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No gustspeed in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rGustSpeed := STRING_TO_REAL(psHelp^);
(* *)
wStateMachine := 120;
END_IF
120: (* Search for 'solarrad' string in the HTML file *)
sSearchedString := 'input name="solarrad" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No solarrad in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rSolarRad := STRING_TO_REAL(psHelp^);
(* *)
wStateMachine := 130;
END_IF
130: (* Search for 'uv' string in the HTML file *)
sSearchedString := 'input name="uv" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No uv in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
iUV := STRING_TO_INT(psHelp^);
(* *)
wStateMachine := 140;
END_IF
140: (* Search for 'uvi' string in the HTML file *)
sSearchedString := 'input name="uvi" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No uvi in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
iUVI := STRING_TO_INT(psHelp^);
(* *)
wStateMachine := 150;
END_IF
150: (* Search for 'rainofhourly' string in the HTML file *)
sSearchedString := 'input name="rainofhourly" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No rainofhourly in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rRainOfHourly := STRING_TO_REAL(psHelp^);
(* *)
wStateMachine := 160;
END_IF
160: (* Search for 'rainofdaily' string in the HTML file *)
sSearchedString := 'input name="rainofdaily" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No rainofdaily in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rRainOfDaily := STRING_TO_REAL(psHelp^);
(* *)
wStateMachine := 170;
END_IF
170: (* Search for 'rainofweekly' string in the HTML file *)
sSearchedString := 'input name="rainofweekly" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No rainofweekly in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rRainOfWeekly := STRING_TO_REAL(psHelp^);
(* *)
wStateMachine := 180;
END_IF
180: (* Search for 'rainofmonthly' string in the HTML file *)
sSearchedString := 'input name="rainofmonthly" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No rainofmonthly in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rRainOfMonthly := STRING_TO_REAL(psHelp^);
(* *)
wStateMachine := 200;
END_IF
200: (* Search for 'rainofyearly' string in the HTML file *)
sSearchedString := 'input name="rainofyearly" disabled="disabled" type="text" class="item_2" style="WIDTH: 80px" value="';
SearchForString;
IF xFail THEN
sStatus := 'ERROR: No rainofyearly in file';
xStart:= FALSE;
diError := 16#00000001;
wStateMachine := 999;
ELSE
(* Get value content *)
i := 0;
bHelp := pabXmlHandler^[i];
WHILE bHelp <> 16#22 AND bHelp <> 16#00 DO
abHelp[i] := bHelp;
i := i + 1;
bHelp := pabXmlHandler^[i];
END_WHILE
abHelp[i] := 16#00;
psHelp := ADR(abHelp);
rRainOfYearly := STRING_TO_REAL(psHelp^);
(**)
sStatus := 'Sucessfully executed';
diError := 0;
xStart := FALSE;
(**)
wStateMachine := 0;
END_IF
999: (* Error *)
xStart := FALSE;
wStateMachine := 0;
ELSE
xStart := FALSE;
wStateMachine := 0;
END_CASE
Funkcja (Makro?) SearchForString (nie mojego autorstwa):
Kod: [Zaznacz]
(* Find block in stream *)
uiPos := HTTP_FindBlock(
pabXmlHandler,
uiXmlFileStreamLen,
ADR(sSearchedString),
LEN(sSearchedString));
IF uiPos > 0 THEN
(* Update index where the handler points to and update the stream length *)
uiXmlHandlerIndex := LEN(sSearchedString) + uiPos - 1 + uiXmlHandlerIndex;
pabXmlHandler := ADR(abXmlFileStream[uiXmlHandlerIndex]);
uiXmlStreamLen := uiXmlFileStreamLen - uiXmlHandlerIndex;
xFail := FALSE;
ELSE
(* If not presented ignore it *)
xFail := TRUE;
END_IF