1 package iotcode.DoorlockActuator;
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 iotcode.annotation.*;
11 import iotruntime.slave.*;
12 import iotcode.interfaces.*;
13 import iotruntime.zigbee.*;
15 /** Class Smartthings sensor driver for Smartthings sensor devices.
17 * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
21 public class DoorlockActuator implements IoTZigbeeCallback, SmartthingsActuator {
23 private final int TIMEOUT_FOR_RESEND_MSEC = 900;
25 private IoTZigbee zigConnection = null;
26 private boolean didClose; // make sure that the clean up was done correctly
27 private boolean detectStatus = false;
29 private int detectedValue = 0;
30 private Date timestampOfLastDetecting = null;
32 private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
33 private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
34 private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
35 private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
36 private AtomicBoolean didBind = new AtomicBoolean(false);
37 private AtomicBoolean didDoorLockConfigureReporting = new AtomicBoolean(false); // made by Jiawei
38 static Semaphore gettingLatestDataMutex = new Semaphore(1);
40 private List < SmartthingsActuatorSmartCallback > callbackList = new CopyOnWriteArrayList < SmartthingsActuatorSmartCallback > ();
42 private int sensorId = 0;
44 @config private IoTSet<IoTDeviceAddress> doorlockActuatorUdpAddress;
45 @config private IoTSet<IoTZigbeeAddress> doorlockActuatorZigbeeAddress;
47 public DoorlockActuator(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
48 doorlockActuatorUdpAddress = dSet;
49 doorlockActuatorZigbeeAddress = zigSet;
52 public DoorlockActuator() {
57 if (didAlreadyInit.compareAndSet(false, true) == false) {
58 return; // already init
61 didAlreadyClose.set(false);
64 Iterator itrUdp = doorlockActuatorUdpAddress.iterator();
65 Iterator itrZig = doorlockActuatorZigbeeAddress.iterator();
67 zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
70 System.out.println("DEBUG: Allocate iterators to print out addresses!");
71 Iterator itrDebugUdp = doorlockActuatorUdpAddress.iterator();
72 IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
73 System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
74 System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
75 System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
77 Iterator itrDebugZig = doorlockActuatorZigbeeAddress.iterator();
78 IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
79 System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
81 zigConnection.registerCallback(this);
82 System.out.println("Register callback!");
84 System.out.println("Initialized!");
91 System.out.println("Sending Management Permit Joining Request");
92 // TODO: Might/might not need to send this 3 times
93 // for(int z=0; z<3; z++){
94 zigConnection.sendManagementPermitJoiningRequest(0x0002, 0x0036, 0x00);
99 while(!didBind.get()){
100 System.out.println("Sending Bind Request");
101 zigConnection.sendBindRequest(0x0003, 0x0101, 0x02);
105 while(!didDoorLockConfigureReporting.get()){
106 System.out.println("Sending Door Lock: Configure Reporting");
107 zigConnection.sendConfigureReportingCommand(0x0004, 0x0101, 0x0104, 0x01, 0x02, 0x0000, 0x30, 0x0000, 0x100E, null);
111 } catch (Exception e) {
119 * @param value Integer value for actuation
120 * @return boolean Status of sending actuate command
122 public boolean actuate(int value) {
126 System.out.println("Doorlock: Is locking!");
128 System.out.println("Doorlock: Is unlocking!");
129 else { // Failed to send command because of invalid value
130 throw new Error("Doorlock: Actuate value " + value + " is not recognized (only 0 or 1)! Please check your method call...");
133 zigConnection.sendLockOrUnlockDoorRequest(0x0005, 0x0101, 0x0104, 0x02, value);
135 } catch (Exception e) {
142 * requestStatus() method
146 public void requestStatus() {
147 System.out.println("Doorlock: Requesting status... Receiving answer through callback...");
149 zigConnection.sendReadDoorStatusRequest(0x0005, 0x0101, 0x0104, 0x02, 0x10, 0x00, 0x0000);
151 } catch (Exception e) {
157 private void sleep(int multipleTime){
162 Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
163 } catch(Exception e){
169 public int getStatus() {
174 gettingLatestDataMutex.acquire();
177 } catch (Exception e) {
180 gettingLatestDataMutex.release();
185 public boolean isActiveStatus() {
187 int tmp = getStatus();
189 detectStatus = true; // ACTIVE == Door is locked
191 detectStatus = false; // NOT ACTIVE == Door is not locked/not fully locked
195 public void close() {
197 if (didAlreadyClose.compareAndSet(false, true) == false) {
198 return; // already init
201 didAlreadyInit.set(false);
205 zigConnection.close();
206 } catch (Exception e) {
211 public void Finalize() {
217 public void setId(int id) {
230 public long getTimestampOfLastReading() {
234 gettingLatestDataMutex.acquire();
235 tmp = (Date)timestampOfLastDetecting.clone();
237 } catch (Exception e) {
240 gettingLatestDataMutex.release();
241 long retLong = tmp.getTime();
246 public void newMessageAvailable(IoTZigbeeMessage _zm) {
249 if (_zm instanceof IoTZigbeeMessageZdoBindResponse) {
250 IoTZigbeeMessageZdoBindResponse message = (IoTZigbeeMessageZdoBindResponse)_zm;
251 if (message.getSucceeded()) {
255 else if (_zm instanceof IoTZigbeeMessageZclConfigureReportingResponse){
256 IoTZigbeeMessageZclConfigureReportingResponse message = (IoTZigbeeMessageZclConfigureReportingResponse)_zm;
257 if (message.getAllSuccess()) {
258 didDoorLockConfigureReporting.set(true);
261 else if (_zm instanceof IoTZigbeeMessageZclReadAttributesResponse) {
262 IoTZigbeeMessageZclReadAttributesResponse message = (IoTZigbeeMessageZclReadAttributesResponse)_zm;
263 List <IoTZigbeeMessageZclReadAttributesResponse.Attribute> attrList = message.getAttributes();
265 if (attrList.size() == 1) {
266 if(attrList.get(0).getAttributeId() == 0) {
267 byte[] data = attrList.get(0).getData();
271 gettingLatestDataMutex.acquire();
272 detectedValue = value;
273 timestampOfLastDetecting = new Date();
274 } catch (Exception e) {
277 gettingLatestDataMutex.release();
280 for (SmartthingsActuatorSmartCallback cb : callbackList) {
281 cb.newActuatorReadingAvailable(this.getId(), this.getStatus(), this.isActiveStatus());
283 } catch (Exception e) {
291 public void registerCallback(SmartthingsActuatorSmartCallback _callbackTo) {
292 callbackList.add(_callbackTo);