1 package iotcode.MotionSensor;
3 // Standard Java Packages
5 import java.util.concurrent.atomic.AtomicBoolean;
6 import java.util.concurrent.CopyOnWriteArrayList;
7 import java.util.concurrent.Semaphore;
10 //import iotchecker.qual.*;
11 import iotcode.annotation.*;
14 import iotruntime.slave.*;
15 import iotcode.interfaces.*;
16 import iotruntime.zigbee.*;
18 /** Class Smartthings sensor driver for Smartthings sensor devices.
20 * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
24 public class MotionSensor implements IoTZigbeeCallback, SmartthingsSensor {
26 private final int TIMEOUT_FOR_RESEND_MSEC = 900;
28 private IoTZigbee zigConnection = null;
29 private boolean didClose; // make sure that the clean up was done correctly
30 private boolean detectStatus = false;
32 private int detectedValue = 0;
33 private Date timestampOfLastDetecting = null;
35 private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
36 private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
37 private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
38 private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
39 static Semaphore gettingLatestDataMutex = new Semaphore(1);
41 private List < SmartthingsSensorSmartCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorSmartCallback > ();
43 private int sensorId = 0;
45 @config private IoTSet<IoTDeviceAddress> motionSensorUdpAddress;
46 @config private IoTSet<IoTZigbeeAddress> motionSensorZigbeeAddress;
48 // TODO: Test constructor
49 //public MotionSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
50 //motionSensorUdpAddress = dSet;
51 //motionSensorZigbeeAddress = zigSet;
54 public MotionSensor() {
59 if (didAlreadyInit.compareAndSet(false, true) == false) {
60 return; // already init
63 didAlreadyClose.set(false);
66 Iterator itrUdp = motionSensorUdpAddress.iterator();
67 Iterator itrZig = motionSensorZigbeeAddress.iterator();
69 zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
72 System.out.println("DEBUG: Allocate iterators to print out addresses!");
73 Iterator itrDebugUdp = motionSensorUdpAddress.iterator();
74 IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
75 System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
76 System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
77 System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
79 Iterator itrDebugZig = motionSensorZigbeeAddress.iterator();
80 IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
81 System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
83 zigConnection.registerCallback(this);
84 System.out.println("Register callback!");
86 System.out.println("Initialized!");
91 System.out.println("Sending Management Permit Joining Request");
92 for(int z=0; z<3; z++){
93 zigConnection.sendManagementPermitJoiningRequest(0x0001, 0x0036, 0x00);
98 while (!didWriteAttrb.get()) {
99 System.out.println("Sending Write Attribute Request");
100 zigConnection.sendWriteAttributesCommand(0x0002, 0x0500, 0x0104, 0x01);
105 System.out.println("Sending Enrollment Reponse");
106 zigConnection.sendEnrollmentResponse(0x0003, 0x0500, 0x0104, 0x01);
109 } catch (Exception e) {
115 private void sleep(int multipleTime){
120 Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
121 } catch(Exception e){
126 public void close() {
128 if (didAlreadyClose.compareAndSet(false, true) == false) {
129 return; // already init
132 didAlreadyInit.set(false);
136 zigConnection.close();
137 } catch (Exception e) {
143 public void Finalize() {
149 public void setId(int id) {
161 public int getValue() {
165 gettingLatestDataMutex.acquire();
168 } catch (Exception e) {
171 gettingLatestDataMutex.release();
177 // - 24 = no motion = false
178 // - 26 = motion = true
179 // After getting 26, if there is no motion for ~12 seconds then we get back 24
180 public boolean isActiveValue() {
182 int tmp = getValue();
185 else // Getting 24 here
186 detectStatus = false;
191 public long getTimestampOfLastReading() {
195 gettingLatestDataMutex.acquire();
196 tmp = (Date)timestampOfLastDetecting.clone();
198 } catch (Exception e) {
201 gettingLatestDataMutex.release();
202 long retLong = tmp.getTime();
207 public void newMessageAvailable(IoTZigbeeMessage _zm) {
210 if(_zm instanceof IoTZigbeeMessageZclZoneStatusChangeNotification){
211 IoTZigbeeMessageZclZoneStatusChangeNotification message = (IoTZigbeeMessageZclZoneStatusChangeNotification)_zm;
212 if(message.getSuccessOrFail()){
216 gettingLatestDataMutex.acquire();
217 detectedValue = message.getStatus();
218 timestampOfLastDetecting = new Date();
219 } catch (Exception e) {
222 gettingLatestDataMutex.release();
224 for (SmartthingsSensorSmartCallback cb : callbackList) {
225 cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
227 } catch (Exception e) {
233 } else if (_zm instanceof IoTZigbeeMessageZclWriteAttributesResponse) {
234 IoTZigbeeMessageZclWriteAttributesResponse message = (IoTZigbeeMessageZclWriteAttributesResponse)_zm;
235 if (message.getSuccessOrFail()) {
236 didWriteAttrb.set(true);
241 public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
242 callbackList.add(_callbackTo);