INCLUDE rtcu.inc
VAR_INPUT
END_VAR;
VAR_OUTPUT
END_VAR;
VAR
target_uuid : STRING := "A565CC84-1E0E-4B5A-B2D3-17C98FF5410A";
target_MAC : STRING := "";
scanning : BOOL := TRUE;
END_VAR;
FUNCTION readIntBE:INT;
VAR_INPUT
p : PTR;
END_VAR;
VAR
tmp : INT;
END_VAR;
memcpy(dst:=ADDR(tmp)+1, src:=p, len:=1);
memcpy(dst:=ADDR(tmp), src:=p+1, len:=1);
readIntBE := tmp;
END_FUNCTION;
FUNCTION parseProxUuid:STRING;
VAR_INPUT
p : PTR;
END_VAR;
VAR
str : STRING;
data : ARRAY[0..16] OF USINT;
i : INT;
END_VAR;
memcpy(dst:=ADDR(data), src:=p, len:=16);
str := sintToHex(v:=data[0])+sintToHex(v:=data[1])+sintToHex(v:=data[2])+sintToHex(v:=data[3])
+"-"+sintToHex(v:=data[4])+sintToHex(v:=data[5])+"-"+sintToHex(v:=data[6])+sintToHex(v:=data[7])
+"-"+sintToHex(v:=data[8])+sintToHex(v:=data[9])+"-"+sintToHex(v:=data[10])+sintToHex(v:=data[11])
+sintToHex(v:=data[12])+sintToHex(v:=data[13])+sintToHex(v:=data[14])+sintToHex(v:=data[15]);
parseProxUuid := str;
END_FUNCTION;
FUNCTION ParseProx : INT;
VAR_INPUT
mac : STRING;
p : PTR;
len : INT;
END_VAR;
VAR
uuid : STRING;
major : UINT;
minor : UINT;
meas_power : SINT;
END_VAR;
ParseProx := 0;
uuid := parseProxUuid(p:=p);
major := readIntBE(p:=p+16);
minor := readIntBE(p:=p+18);
memcpy(dst:=ADDR(meas_power), src:=p+20, len:=1);
DebugFmt(message:=" "+mac);
DebugFmt(message:=" "+uuid);
DebugFmt(message:=" Major: "+intToHex(v:=major));
DebugFmt(message:=" Minor: "+intToHex(v:=minor));
DebugFmt(message:=" Measured power: \1 dB", v1:=meas_power );
IF uuid = target_uuid THEN
DebugFmt(message:=" Button short pushed: \1", v1:=(minor AND 1));
DebugFmt(message:=" Button long pushed: \1", v1:=(minor AND 2));
DebugFmt(message:=" Movement: \1", v1:=(minor AND 4));
DebugFmt(message:=" Free Fall: \1", v1:=(minor AND 8));
ParseProx := 1;
END_IF;
END_FUNCTION;
FUNCTION ParseBeacon : INT;
VAR_INPUT
mac : STRING;
p : PTR;
len : INT;
END_VAR;
VAR
b_type : UINT;
END_VAR;
ParseBeacon := 0;
memcpy(dst:=ADDR(b_type), src:=p, len:=2);
IF b_type = 16#1502 THEN
ParseBeacon := ParseProx(mac:= mac, p:=p+2, len:=len-2);
END_IF;
END_FUNCTION;
FUNCTION CALLBACK cbAdvMan;
VAR_INPUT
mac : STRING;
ev_type : UINT;
adv_type : USINT;
data : PTR;
len : INT;
rssi : SINT;
arg : DINT;
END_VAR;
VAR
cid : UINT;
rc : INT;
END_VAR;
IF adv_type = 16#FF THEN
memcpy(dst:=ADDR(cid), src:=data, len:=2);
IF cid = 16#004c THEN
rc := ParseBeacon(mac:=mac, p:=data+2, len := len-2);
IF rc = 1 AND scanning THEN
target_MAC := MAC;
rc := bleObserverStop();
DebugFmt(message:="bleObserverStop: \1", v1:=rc);
scanning := FALSE;
rc := bleAcceptFilterAdd(mac:=target_MAC);
DebugFmt(message:="bleAcceptFilterAdd: \1", v1:=rc);
rc := bleObserverStart(
scan_type:=1,
filter_policy := 1
);
DebugFmt(message:="bleObserverStart: \1", v1:=rc);
END_IF;
END_IF;
END_IF;
END_FUNCTION;
THREAD_BLOCK beaconThread;
VAR
rc, rc2 : INT;
i, j : INT;
s, c : UINT;
uuid : STRING;
primary : BOOL;
flags : DINT;
dev : SYSHANDLE;
bat_level_id : UINT;
bat_level : USINT;
size : INT;
state : INT := 0;
old_state : INT:= -1;
running : BOOL;
END_VAR;
DebugMsg(message:="Starting beacon thread");
running := TRUE;
rc := bleObserverStop();
DebugFmt(message:="bleObserverStop: \1", v1:=rc);
WHILE running DO
IF old_state <> state THEN
DebugFmt(message:="S: \1 => \2", v1:=old_state, v2:=state);
old_state:=state;
END_IF;
CASE state OF
0:
DebugFmt(message:="Connect...");
rc := bleConnect(dev:=dev, mac:=target_mac);
DebugFmt(message:="bleConnect: \1", v1:=rc);
IF rc = _BLE_OK THEN
state := 1;
ELSE
state := state+100;
END_IF;
1:
rc := bleDeviceStatus(dev:=dev);
DebugFmt(message:="bleDeviceStatus: \1, "+bleDeviceMacGet(dev:=dev), v1:=rc);
IF rc = 2 THEN
DebugFmt(message:="connection lost");
state := 10;
ELSIF rc = 5 THEN
state := state+100;
ELSIF rc = 10 THEN
state := state+100;
ELSIF rc = 20 THEN
state := 2;
ELSIF rc > 20 THEN
state := 3;
END_IF;
2:
rc := bleServiceCacheUpdate(dev:=dev);
DebugFmt(message:="bleServiceCacheUpdate: \1", v1:=rc);
IF rc = _BLE_OK THEN
state := 3;
ELSE
state := 10;
END_IF;
3:
state := state+100;
DebugMsg(message:="-- Services: --");
i := 0;
REPEAT
rc := bleServiceGet(dev:=dev, idx := i, service:=s, uuid:=uuid, primary := primary);
IF rc = _BLE_OK THEN
DebugFmt(message:=" Service: \1, primary: \2, UUID: "+UUID, v1:=s, v2:=INT(primary));
j := 0;
REPEAT
rc2 := bleCharGet(dev:=dev, service:=s, idx := j, char:=c, uuid:=uuid, flags := flags);
IF rc2 = _BLE_OK THEN
DebugFmt(message:=" Service: \1, Char: \2, flags: \4, UUID: "+UUID, v1:=s, v2:=c, v3:=j, v4:=flags);
IF uuid = "00002a19-0000-1000-8000-00805f9b34fb" THEN
bat_level_id := c;
state := 4;
END_IF;
ELSE
DebugFmt(message:=" End(\2): \1", v1:=rc2, v2:=j);
END_IF;
j:=j+1;
UNTIL rc2 <> _BLE_OK
END_REPEAT;
ELSE
DebugFmt(message:=" End(\2): \1", v1:=rc, v2:=i);
END_IF;
i:=i+1;
UNTIL rc <> _BLE_OK
END_REPEAT;
4:
size:=1;
rc := bleReadVal(dev:=dev, char:=bat_level_id, size := size, data := ADDR(bat_level));
DebugFmt(message:="bleReadVal(\2): \1", v1:=rc, v2:=bat_level_id);
IF rc = 1 THEN
DebugFmt(message:="Battery level: \1 %", v1:=bat_level);
state := 5;
ELSIF rc = -19 THEN
DebugFmt(message:="connection lost");
state := 10;
ELSE
state := state+100;
END_IF;
5:
state := 10;
10:
DebugMsg(message:="Disconnecting...");
rc := bleDisConnect(dev:=dev);
DebugFmt(message:="bleDisconnect: \1", v1:=rc);
IF rc = _BLE_OK THEN
running := FALSE;
state := 100;
ELSE
state := state+100;
END_IF;
END_CASE;
IF state >= 100 THEN
state := state -100;
Sleep(delay:=5000);
END_IF;
END_WHILE;
rc := bleObserverStart(
scan_type:=1,
filter_policy := 1
);
DebugFmt(message:="bleObserverStart: \1", v1:=rc);
END_THREAD_BLOCK;
VAR
beaconThr:beaconThread;
END_VAR;
PROGRAM beacon;
VAR
rc : INT;
sms : gsmIncomingSMS;
END_VAR;
rc := blePower(power:=ON);
DebugFmt(message:="blePower: \1", v1:=rc);
rc := bleAcceptFilterClear();
DebugFmt(message:="bleAcceptFilterClear: \1", v1:=rc);
rc := bleRegisterAdvData(cb_Adv:=@cbAdvMan, adv_type := 16#FF);
DebugFmt(message:="BleRegisterAdvData: \1", v1:=rc);
rc := bleObserverStart(
scan_type:=1,
filter_policy := 0
);
DebugFmt(message:="bleObserverStart: \1", v1:=rc);
BEGIN
sms();
IF sms.status > 0 THEN
IF sms.message = "connect" THEN
IF target_MAC <> "" THEN
beaconThr();
ELSE
DebugMsg(message:="Target not found");
END_IF;
END_IF;
END_IF;
END;
END_PROGRAM;
|