INCLUDE rtcu.inc
#DEFINE USE_TLS 1
#DEFINE USE_ST 1
FUNCTION INTERFACE dumpValue;
VAR_INPUT
json : SYSHANDLE;
prefix : STRING;
key : STRING;
idx : INT := -1;
type : INT;
txt : STRING;
END_VAR;
END_FUNCTION;
FUNCTION dumpStructure;
VAR_INPUT
json : SYSHANDLE;
prefix : STRING;
END_VAR;
VAR
type, i, rc : INT;
key : STRING;
END_VAR;
type := jsonGetType(o:=json, idx:=-1);
IF type = 1 THEN
DebugMsg(message:=prefix+"{");
i := 0;
REPEAT
rc := jsonGetKey(o:=json, idx:= i, key:=key, type:=type);
IF rc = 1 THEN
dumpValue(json:=json, prefix:=prefix+" ", txt:=key+" ", key:=key, idx:=-1, type:=type);
END_IF;
i := i+1;
UNTIL rc < 0
END_REPEAT;
DebugMsg(message:=prefix+"}");
ELSIF type = 2 THEN
DebugMsg(message:=prefix+"[");
FOR i := 0 TO jsonArraySize(o:=json)-1 DO
dumpValue(json:=json, prefix:=prefix+" ", txt:="["+intToStr(v:=i)+"] ", key:="", idx:=i, type:=jsonGetType(o:=json, idx:= i));
END_FOR;
DebugMsg(message:=prefix+"]");
END_IF;
END_FUNCTION;
FUNCTION IMPLEMENTATION dumpValue;
VAR
rc : INT;
tmp : SYSHANDLE;
str : STRING;
d : DINT;
b : BOOL;
f : DOUBLE;
END_VAR;
CASE type OF
1,2:
DebugFmt(message:=prefix+txt+":");
rc := jsonGetValue(o:=json, key:=key, idx:=idx, value := tmp);
dumpStructure(json:=tmp, prefix := prefix);
rc := jsonFree(o:=tmp);
3:
jsonGetString(o:=json, key:=key, idx:=idx, value :=str);
DebugFmt(message:=prefix+txt+": "+str);
4:
jsonGetInt(o:=json, key:=key, idx:=idx, value :=d);
DebugFmt(message:=prefix+txt+": \4", v4:=d);
5:
jsonGetFloat(o:=json, key:=key, idx:=idx, value :=f);
DebugFmt(message:=prefix+txt+": "+doubleToStr(v:=f));
6:
jsonGetBool(o:=json, key:=key, idx:=idx, value :=b);
IF b THEN
DebugFmt(message:=prefix+txt+": TRUE");
ELSE
DebugFmt(message:=prefix+txt+": FALSE");
END_IF;
7:
DebugFmt(message:=prefix+txt+": NULL");
END_CASE;
END_FUNCTION;
VAR
clock : clockLinsecToTime;
jsonStats : jsonHandleStats;
END_VAR;
FUNCTION linsecToStr : STRING;
VAR_INPUT
linsec : DINT;
END_VAR;
VAR
str : STRING;
END_VAR;
clock(linsec:=linsec);
str:=strFormat(format:="\1-\2-\3 ", v1:=clock.year, v2:=clock.month, v3:=clock.day);
str:=str+strFormat(format:="\1:\2:\3", v1:=clock.hour, v2:=clock.minute, v3:=clock.second);
linsecToStr:=str;
END_FUNCTION;
FUNCTION dumpCert;
VAR_INPUT
req : SYSHANDLE;
rip : DINT;
END_VAR;
VAR
rc : INT;
str : STRING;
d : DINT;
i : INT;
ip : DINT;
END_VAR;
rc := restReqClientCertPresent(req:=req);
IF rc = 1 THEN
DebugFmt(message:="Client cert present");
rc := restReqClientCertSubjectGet(req:=req, str:=str);
DebugFmt(message:=" Subject: "+str+": \1", v1:=rc);
rc := restReqClientCertSubjectCNGet(req:=req, str:=str);
DebugFmt(message:=" CN: "+str+": \1", v1:=rc);
rc := restReqClientCertIssuerGet(req:=req, str:=str);
DebugFmt(message:=" Issuer: "+str+": \1", v1:=rc);
rc := restReqClientCertVersionGet(req:=req);
DebugFmt(message:=" Version: \1", v1:=rc);
d := restReqClientCertValidFrom(req:=req);
DebugFmt(message:=" Valid from: \4, "+linsecToStr(linsec:=d), v4:=d);
d := restReqClientCertValidTo(req:=req);
DebugFmt(message:=" Valid to: \4, "+linsecToStr(linsec:=d), v4:=d);
rc := restReqClientCertSerialGet(req:=req, str:=str);
DebugFmt(message:=" Serial: "+str+": \1", v1:=rc);
rc := restReqClientCertFingerprintGet(req:=req, type:=0, str:=str);
DebugFmt(message:=" SHA1 : "+str+": \1", v1:=rc);
rc := restReqClientCertFingerprintGet(req:=req, type:=1, str:=str);
DebugFmt(message:=" MD51 : "+str+": \1", v1:=rc);
rc := restReqClientCertCheckHostname(req:=req, hostname:="localhost");
DebugFmt(message:=" Match localhost: \1", v1:=rc, v2:=i);
rc := restReqClientCertCheckEmail(req := req, email := "test@example.com");
DebugFmt(message:=" Match test@example.com: \1", v1 := rc);
i := 0;
REPEAT
rc := restReqClientCertSANGet(req:=req, idx:=i, san:=str);
DebugFmt(message:= " SAN[\1]: \2: "+str, v1:=i, v2:=rc);
IF rc = 4 THEN
ip := soAddrToIP(address :=str);
IF ip = rip THEN
DebugMsg(message:="Matching IP found: "+str);
END_IF;
END_IF;
i := i + 1;
UNTIL rc = -21
END_REPEAT;
ELSE
DebugFmt(message:="No client cert present");
END_IF;
END_FUNCTION;
FUNCTION CALLBACK devicesPostCallback: INT;
VAR_INPUT
req : SYSHANDLE;
resp : SYSHANDLE;
arg : DINT;
END_VAR;
VAR
talq_version : STRING;
client_address: STRING;
id : STRING;
json : STRING;
str : STRING;
END_VAR;
restReqHeaderGet(req:=req, name:="talq-version", value:=talq_version);
restReqQueryGet(req:=req, name:="clientAddress", value:=client_address);
restReqQueryGet(req:=req, name:="id", value:=id);
DebugFmt(message:="Request: id: "+id+", client address: "+client_address);
restReqClientAddressGet(req:=req, address:=str);
DebugFmt(message:="Address: "+str);
dumpCert(req:=req, rip := soAddrToIP(address :=str));
restReqBodyGetString(req:=req, str := json);
IF json <> "" THEN
restRespBodySetString(resp:=resp, str := json);
restRespHeaderSet(resp:=resp, name:="Content-Type", value:="application/json");
devicesPostCallback := 201;
ELSE
restRespBodySetString(resp:=resp, str := "{$"key$":$"payloadError$" }");
restRespHeaderSet(resp:=resp, name:="Content-Type", value:="application/json");
devicesPostCallback := 400;
END_IF;
END_FUNCTION;
FUNCTION GenerateJSONFromTemplate:INT;
VAR_INPUT
json : ACCESS SYSHANDLE;
deviceName : STRING;
deviceClassName : STRING;
displayName : STRING;
assetId : STRING;
lampTypeId : STRING;
END_VAR;
VAR
st : SYSHANDLE;
rc : INT;
str : STRING;
jStr : STRING;
END_VAR;
str := STRING_BEGIN
[
{
"address": "00000000-0000-0000-0000-000000000000",
"name": "<deviceName>",
"class": "<deviceClassName>",
"functions": [
{
"id": "basic001",
"type": "BasicFunction",
"displayName": {
"value": "<displayName>"
},
"assetId": {
"value": "<assetId>"
}
},
{
"id": "lampActuator001",
"type": "LampActuatorFunction",
"lampTypeId": {
"value": "<lampTypeId>"
},
"maintenanceFactor": {
"value": 50
},
"maintenancePeriod": {
"value": 12
}
}
]
}
]
STRING_END;
rc := strTemplateCreate(st:=st, str:=str, sov := "<", eov := ">");
DebugFmt(message:="strTemplateCreate: \1", v1:=rc);
rc := strTemplateSetVar(st:=st, name:="deviceName", value:=DeviceName);
DebugFmt(message:="strTemplateSetVar: \1", v1:=rc);
rc := strTemplateSetVar(st:=st, name:="deviceClassName", value:=deviceClassName);
DebugFmt(message:="strTemplateSetVar: \1", v1:=rc);
rc := strTemplateSetVar(st:=st, name:="assetId", value:=assetId);
DebugFmt(message:="strTemplateSetVar: \1", v1:=rc);
rc := strTemplateSetVar(st:=st, name:="lampTypeId", value:=lampTypeId);
DebugFmt(message:="strTemplateSetVar: \1", v1:=rc);
rc := strTemplateGenerateString(st:=st, str:=jStr);
rc := strTemplateFree(st:=st);
DebugFmt(message:="strTemplateFree: \1", v1:=rc);
rc := jsonFromString(o:=json, str:=jStr);
DebugFmt(message:="jsonFromString: \1", v1:=rc);
GenerateJSONFromTemplate := rc;
END_FUNCTION;
FUNCTION GenerateJSON:INT;
VAR_INPUT
json : ACCESS SYSHANDLE;
END_VAR;
VAR
rc : INT;
devices, device, functions, func, tmp : SYSHANDLE;
handles, data:DINT;
END_VAR;
rc := jsonCreateArray(o:=devices);
rc := jsonCreateObject(o:=device);
rc := jsonSetValueString(o:=device, key := "address",
value := "00000000-0000-0000-0000-000000000000");
rc := jsonSetValueString(o:=device, key := "name", value := "<deviceName>");
rc := jsonSetValueString(o:=device, key := "class", value := "<deviceClassName>");
rc := jsonCreateArray(o:=functions);
rc := jsonCreateObject(o:=func);
rc := jsonSetValueString(o:=func, key := "id", value := "basic001");
rc := jsonSetValueString(o:=func, key := "type", value := "basicFunction");
rc := jsonCreateObject(o:=tmp);
rc := jsonSetValueString(o:=tmp, key := "value", value := "<displayName>");
rc := jsonSetValue(o:=func, key := "displayName", value := tmp);
rc := jsonFree(o:=tmp);
rc := jsonCreateObject(o:=tmp);
rc := jsonSetValueString(o:=tmp, key := "value", value := "<assetId>");
rc := jsonSetValue(o:=func, key := "assetId", value := tmp);
rc := jsonFree(o:=tmp);
rc := jsonAddValue(o:=functions, value:=func);
rc := jsonFree(o:=func);
rc := jsonCreateObject(o:=func);
rc := jsonSetValueString(o:=func, key := "id", value := "lampActuator001");
rc := jsonSetValueString(o:=func, key := "type", value := "LampActuatorFunction");
rc := jsonCreateObject(o:=tmp);
rc := jsonSetValueString(o:=tmp, key := "value", value := "<lampTypeId>");
rc := jsonSetValue(o:=func, key := "lampTypeId", value := tmp);
rc := jsonFree(o:=tmp);
rc := jsonCreateObject(o:=tmp);
rc := jsonSetValueInt(o:=tmp, key := "value", value := 50);
rc := jsonSetValue(o:=func, key := "maintenanceFactor", value := tmp);
rc := jsonFree(o:=tmp);
rc := jsonCreateObject(o:=tmp);
rc := jsonSetValueInt(o:=tmp, key := "value", value := 12);
rc := jsonSetValue(o:=func, key := "maintenancePeriod", value := tmp);
rc := jsonFree(o:=tmp);
rc := jsonAddValue(o:=functions, value:=func);
rc := jsonFree(o:=func);
rc := jsonSetValue(o:=device, key := "functions", value := functions);
rc := jsonFree(o:=functions);
rc := jsonAddValue(o:=devices, value:=device);
rc := jsonFree(o:=device);
json := devices;
END_FUNCTION;
FUNCTION SendRequest;
VAR
str : STRING;
req, resp : SYSHANDLE;
json : SYSHANDLE;
rc : INT;
END_VAR;
DebugMsg(message:="--------");
IF USE_ST = 1 THEN
rc := GenerateJSONFromTemplate(json:=json, deviceName:="dev1", assetId:="asset 1", lampTypeId:="lamp 1");
ELSE
rc := GenerateJson(json:=json);
END_IF;
IF USE_TLS = 1 THEN
rc := restReqCreate(req:=req, method := "POST",
url := "https://127.0.0.1/devices/1234",
check_hostname:=OFF);
ELSE
rc := restReqCreate(req:=req, method := "POST",
url := "http://127.0.0.1/devices/1234");
END_IF;
jsonStats();
IF jsonStats.status >0 THEN
DebugFmt(message:="JSON status: \1 handle(s)", v1:=jsonStats.no_handles);
END_IF;
rc := restReqQuerySet(req:=req, name := "clientAddress",
value:="110a8321-e34c-112p5-b567-566655648453");
rc := restReqHeaderSet(req:=req, name := "talq-version", value:="2.1.0");
rc := restReqBodySetJSON(req:=req, json:=json);
rc := jsonFree(o:=json);
rc := restReqHeaderSet(req:=req, name:="Accept", value:="application/json");
IF USE_TLS = 1 THEN
rc := restReqClientCertSet(req:=req, cert:="client");
DebugFmt(message:="restReqClientCertSet: \1", v1:=rc);
END_IF;
rc := restClientRequest(req:=req, resp := resp);
DebugFmt(message:="Send request: \1", v1:=rc);
IF rc = 201 THEN
rc := restRespBodyGetString(resp:=resp, str := str);
DebugFmt(message:="data: "+str);
rc := restRespBodyGetJSON(resp:=resp, json := json);
rc := jsonToString(o:=json, str:=str, indent:=0);
dumpStructure(json:=json);
rc := jsonFree(o:=json);
DebugFmt(message:="JSON: "+str);
rc := restRespFree(resp:=resp);
END_IF;
rc := restReqFree(req:=req);
END_FUNCTION;
PROGRAM rest_1;
VAR
serv : SYSHANDLE;
rc : INT;
END_VAR;
netOpen(iface:=2);
IF USE_TLS = 1 THEN
rc := restServerCreate(handle:=serv, port:=443, cert:="server", accept_ca:="ca");
ELSE
rc := restServerCreate(handle:=serv, port:=80);
END_IF;
DebugFmt(message:="restServerCreate: \1", v1:=rc);
rc := restServerEndpointAdd(handle:=serv, method:="*", url_prefix:="/devices",
url_format:="/:id", cb_func:=@devicesPostCallback);
rc := restServerStart(handle:=serv);
DebugFmt(message:="restServerStart: \1", v1:=rc);
BEGIN
SendRequest();
Sleep(delay:=30000);
END;
END_PROGRAM;
|