1 // Standard Java Packages
2 import java.util.Iterator;
4 import java.util.ArrayList;
6 import java.util.concurrent.atomic.AtomicBoolean;
7 import java.util.concurrent.CopyOnWriteArrayList;
8 import java.util.concurrent.Semaphore;
11 // Checker annotations
12 //import iotchecker.qual.*;
15 import iotruntime.slave.*;
16 //import iotcode.interfaces.MoistureSensor;
17 //import iotcode.interfaces.MoistureSensorSmartCallback;
18 import iotruntime.zigbee.*;
19 //import iotcode.annotation.*;
21 public class SpruceSensor implements IoTZigbeeCallback, MoistureSensor {
23 private final int TIMEOUT_FOR_RESEND_MSEC = 1000;
25 private IoTZigbee zigConnection = null;
26 private boolean didClose; // make sure that the clean up was done correctly
28 private float humidity = 0;
29 private Date timestampOfLastHumidity = null;
31 private AtomicBoolean didBind = new AtomicBoolean(false);
32 private AtomicBoolean didConfigureReporting = new AtomicBoolean(false);
33 private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
34 private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
35 static Semaphore gettingLatestDataMutex = new Semaphore(1);
37 private List < MoistureSensorSmartCallback > callbackList = new CopyOnWriteArrayList < MoistureSensorSmartCallback > ();
39 private int sensorId = 0;
41 @config private IoTSet<IoTDeviceAddress> devUdpAddress;
42 @config private IoTSet<IoTZigbeeAddress> devZigbeeAddress;
44 public SpruceSensor(IoTSet<IoTDeviceAddress> _devUdpAddress, IoTSet<IoTZigbeeAddress> _devZigbeeAddress) {
45 devUdpAddress = _devUdpAddress;
46 devZigbeeAddress = _devZigbeeAddress;
51 if (didAlreadyInit.compareAndSet(false, true) == false) {
52 return; // already init
55 didAlreadyClose.set(false);
58 Iterator itrUdp = devUdpAddress.iterator();
59 Iterator itrZig = devZigbeeAddress.iterator();
61 zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
64 System.out.println("DEBUG: Allocate iterators to print out addresses!");
65 Iterator itrDebugUdp = devUdpAddress.iterator();
66 IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
67 System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
68 System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
69 System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
71 Iterator itrDebugZig = devZigbeeAddress.iterator();
72 IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
73 System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
75 zigConnection.registerCallback(this);
76 System.out.println("Register callback!");
78 System.out.println("Initialized!");
80 while (!didBind.get()) {
81 zigConnection.sendBindRequest(0x0001, 0x0405, 0x01);
82 System.out.println("Sending bind request!");
84 Thread.sleep(TIMEOUT_FOR_RESEND_MSEC);
85 } catch (Exception e) {
90 while (!didConfigureReporting.get()) {
91 zigConnection.sendConfigureReportingCommand(0x0001, 0x0405, 0x0104, 0x01, 0x0000, 0x21, 0x0001, 0x0001, null);
93 Thread.sleep(TIMEOUT_FOR_RESEND_MSEC);
94 } catch (Exception e) {
98 } catch (Exception e) {
103 public void close() {
105 if (didAlreadyClose.compareAndSet(false, true) == false) {
106 return; // already init
109 didAlreadyInit.set(false);
113 zigConnection.close();
114 } catch (Exception e) {
119 public void Finalize() {
125 public void setId(int id) {
137 public float getMoisture() {
141 gettingLatestDataMutex.acquire();
144 } catch (Exception e) {
147 gettingLatestDataMutex.release();
152 public long getTimestampOfLastReading() {
156 gettingLatestDataMutex.acquire();
157 tmp = (Date)timestampOfLastHumidity.clone();
159 } catch (Exception e) {
162 gettingLatestDataMutex.release();
163 long retLong = tmp.getTime();
168 public void newMessageAvailable(IoTZigbeeMessage _zm) {
170 if (_zm instanceof IoTZigbeeMessageZdoBindResponse) {
171 IoTZigbeeMessageZdoBindResponse message = (IoTZigbeeMessageZdoBindResponse)_zm;
172 if (message.getSucceeded()) {
176 } else if (_zm instanceof IoTZigbeeMessageZclConfigureReportingResponse) {
177 IoTZigbeeMessageZclConfigureReportingResponse message = (IoTZigbeeMessageZclConfigureReportingResponse)_zm;
178 if (message.getAllSuccess()) {
179 didConfigureReporting.set(true);
182 } else if (_zm instanceof IoTZigbeeMessageZclReportAttributes) {
183 IoTZigbeeMessageZclReportAttributes message = (IoTZigbeeMessageZclReportAttributes)_zm;
184 List <IoTZigbeeMessageZclReportAttributes.Attribute> attrList = message.getAttributes();
186 if (attrList.size() == 1) {
187 if (attrList.get(0).getAttributeId() == 0) {
188 byte[] data = attrList.get(0).getData();
190 int value = (data[0] * 256) + data[1];
193 gettingLatestDataMutex.acquire();
194 humidity = (float)value / (float)100.0;
195 timestampOfLastHumidity = new Date();
196 } catch (Exception e) {
199 gettingLatestDataMutex.release();
202 for (MoistureSensorSmartCallback cb : callbackList) {
203 cb.newReadingAvailable(this.getId(), this.getMoisture(), this.getTimestampOfLastReading());
205 } catch (Exception e) {
214 public void registerCallback(MoistureSensorSmartCallback _callbackTo) {
215 callbackList.add(_callbackTo);