1 // Standard Java Packages
3 import java.util.concurrent.atomic.AtomicBoolean;
4 import java.util.concurrent.CopyOnWriteArrayList;
5 import java.util.concurrent.Semaphore;
8 //import iotchecker.qual.*;
9 //import iotcode.annotation.*;
12 import iotruntime.slave.*;
13 //import iotcode.interfaces.*;
14 import iotruntime.zigbee.*;
16 /** Class Smartthings sensor driver for Smartthings sensor devices.
18 * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
22 public class MotionSensor implements IoTZigbeeCallback, SmartthingsSensor {
24 private final int TIMEOUT_FOR_RESEND_MSEC = 900;
26 private IoTZigbee zigConnection = null;
27 private boolean didClose; // make sure that the clean up was done correctly
28 private boolean detectStatus = false;
30 private int detectedValue = 0;
31 private Date timestampOfLastDetecting = null;
33 private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
34 private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
35 private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
36 private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
37 static Semaphore gettingLatestDataMutex = new Semaphore(1);
39 private List < SmartthingsSensorCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorCallback > ();
41 private int sensorId = 0;
43 @config private IoTSet<IoTDeviceAddress> devUdpAddress;
44 @config private IoTSet<IoTZigbeeAddress> devZigbeeAddress;
46 public MotionSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
48 devZigbeeAddress = zigSet;
53 if (didAlreadyInit.compareAndSet(false, true) == false) {
54 return; // already init
57 didAlreadyClose.set(false);
60 Iterator itrUdp = devUdpAddress.iterator();
61 Iterator itrZig = devZigbeeAddress.iterator();
63 zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
66 System.out.println("DEBUG: Allocate iterators to print out addresses!");
67 Iterator itrDebugUdp = devUdpAddress.iterator();
68 IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
69 System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
70 System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
71 System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
73 Iterator itrDebugZig = devZigbeeAddress.iterator();
74 IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
75 System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
77 zigConnection.registerCallback(this);
78 System.out.println("Register callback!");
80 System.out.println("Initialized!");
85 System.out.println("Sending Management Permit Joining Request");
86 for(int z=0; z<3; z++){
87 zigConnection.sendManagementPermitJoiningRequest(0x0001, 0x0036, 0x00);
92 while (!didWriteAttrb.get()) {
93 System.out.println("Sending Write Attribute Request");
94 zigConnection.sendWriteAttributesCommand(0x0002, 0x0500, 0x0104, 0x01);
99 System.out.println("Sending Enrollment Reponse");
100 zigConnection.sendEnrollmentResponse(0x0003, 0x0500, 0x0104, 0x01);
103 } catch (Exception e) {
109 private void sleep(int multipleTime){
114 Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
115 } catch(Exception e){
120 public void close() {
122 if (didAlreadyClose.compareAndSet(false, true) == false) {
123 return; // already init
126 didAlreadyInit.set(false);
130 zigConnection.close();
131 } catch (Exception e) {
137 public void Finalize() {
143 public void setId(int id) {
155 public int getValue() {
159 gettingLatestDataMutex.acquire();
162 } catch (Exception e) {
165 gettingLatestDataMutex.release();
171 // - 24 = no motion = false
172 // - 26 = motion = true
173 // After getting 26, if there is no motion for ~12 seconds then we get back 24
174 public boolean isActiveValue() {
176 int tmp = getValue();
179 else // Getting 24 here
180 detectStatus = false;
185 public long getTimestampOfLastReading() {
189 gettingLatestDataMutex.acquire();
190 tmp = (Date)timestampOfLastDetecting.clone();
192 } catch (Exception e) {
195 gettingLatestDataMutex.release();
196 long retLong = tmp.getTime();
201 public void newMessageAvailable(IoTZigbeeMessage _zm) {
204 if(_zm instanceof IoTZigbeeMessageZclZoneStatusChangeNotification){
205 IoTZigbeeMessageZclZoneStatusChangeNotification message = (IoTZigbeeMessageZclZoneStatusChangeNotification)_zm;
206 if(message.getSuccessOrFail()){
210 gettingLatestDataMutex.acquire();
211 detectedValue = message.getStatus();
212 timestampOfLastDetecting = new Date();
213 } catch (Exception e) {
216 gettingLatestDataMutex.release();
218 for (SmartthingsSensorCallback cb : callbackList) {
219 cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
221 } catch (Exception e) {
227 } else if (_zm instanceof IoTZigbeeMessageZclWriteAttributesResponse) {
228 IoTZigbeeMessageZclWriteAttributesResponse message = (IoTZigbeeMessageZclWriteAttributesResponse)_zm;
229 if (message.getSuccessOrFail()) {
230 didWriteAttrb.set(true);
235 public void registerCallback(SmartthingsSensorCallback _callbackTo) {
236 callbackList.add(_callbackTo);