def setValue(self, value): """ Set parameter value @param value: New parameter value """ # Convert to SwapValue if value.__class__ is SwapValue: # Incorrect length? if self.value.getLength() != value.getLength(): return self.value = value else: # Byte length length = self.byteSize if self.bitSize > 0: length += 1 if type(value) is list: res = value elif type(value) in [str, unicode]: if self.type == SwapType.NUMBER: try: # Possible integer number res = int(value) except ValueError: try: # Possible float number res = float(value) except ValueError: raise SwapException( value + " is not a valid numeric value for " + self.name) elif self.type == SwapType.BINARY: if value.lower() in ["on", "open", "1", "true", "enabled"]: res = 1 else: res = 0 else: # SwapType.STRING res = value else: res = value if type(res) in [int, float]: if self.unit is not None: res -= self.unit.offset res /= self.unit.factor # Convert to integer res = int(res) self.value = SwapValue(res, length) # Update current value self.value = SwapValue(res, length) # Update time stamp self.lastupdate = time.time() # Update register value self.register.update()
def smart_encryption(self, password, decrypt=False): """ Encrypt/Decrypt packet using the Smart Encryption mechanism @param password: Smart Encryption password @param decrypt: Decrypt packet if True. Encrypt otherwise """ # Update password SwapPacket.smart_encrypt_pwd = password # Encryot SwapPacket and CcPacket fields if decrypt: self.nonce ^= password.data[9] self.function ^= password.data[11] ^ self.nonce self.srcAddress ^= password.data[10] ^ self.nonce self.regAddress ^= password.data[8] ^ self.nonce self.regId ^= password.data[7] ^ self.nonce if self.value is not None: pos = 0 newarray = [] for byte in self.value.toList(): byte ^= password.data[pos] ^ self.nonce newarray.append(byte) pos += 1 if pos == 11: pos = 0 self.value = SwapValue(newarray) if not decrypt: self.nonce ^= password.data[9] self._update_ccdata()
def leaveSync(self): """ Ask mote to leave SYNC mode (RXON state) @return True if this command is confirmed from the mote. Return False otherwise """ val = SwapValue(SwapState.RXOFF, length=1) return self.cmdRegisterWack(SwapRegId.ID_SYSTEM_STATE, val)
def restart(self): """ Ask mote to restart @return True if this command is confirmed from the mote. Return False otherwise """ val = SwapValue(SwapState.RESTART, length=1) return self.cmdRegisterWack(SwapRegId.ID_SYSTEM_STATE, val)
def setFreqChannel(self, channel): """ Set mote's frequency channel. Return true if ACK received from mote @param channel: New frequency channel @return True if this command is confirmed from the mote. Return False otherwise """ val = SwapValue(channel, length=1) res = self.cmdRegisterWack(SwapRegId.ID_FREQ_CHANNEL, val)
def setNetworkId(self, netId): """ Set mote's network id. Return true if ACK received from mote @param netId: New Network ID @return True if this command is confirmed from the mote. Return False otherwise """ val = SwapValue(netId, length=2) return self.cmdRegisterWack(SwapRegId.ID_NETWORK_ID, val)
def setAddress(self, address): """ Set mote address @param address: New mote address @return True if this command is confirmed from the mote. Return False otherwise """ val = SwapValue(address, length=1) return self.cmdRegisterWack(SwapRegId.ID_DEVICE_ADDR, val)
def setTxInterval(self, interval): """ Set periodic Tx interval. Return true if ACK received from mote @param interval: New Tx interval @return True if this command is confirmed from the mote. Return False otherwise """ val = SwapValue(interval, length=2) return self.cmdRegisterWack(SwapRegId.ID_TX_INTERVAL, val)
def setSecurity(self, secu): """ Set mote's security option. Return true if ACK received from mote @param secu: Security option @return True if this command is confirmed from the mote. Return False otherwise """ val = SwapValue(secu, length=1) return self.cmdRegisterWack(SwapRegId.ID_SECU_OPTION, val)
def save_txinterval_command(self, interval): """ Save Tx Interval command for later transmission @param interval: New Tx Interval @return True if the command has been received by the target device False if the command was not received by the target device None if the command has been saved for later transmission """ val = SwapValue(interval, length=2) return self.save_command(SwapRegId.ID_TX_INTERVAL, val)
def save_address_command(self, address): """ Save address command for later transmission @param address: New mote address @return True if the command has been received by the target device False if the command was not received by the target device None if the command has been saved for later transmission """ val = SwapValue(address, length=1) return self.save_command(SwapRegId.ID_DEVICE_ADDR, val)
def sendSwapCmd(self, value): """ Send SWAP command for the current endpoint @param value: New endpoint value @return Expected SWAP status response to be received from the mote """ # Convert to SwapValue if value.__class__ is SwapValue: swap_value = value else: # Byte length length = self.byteSize if self.bitSize > 0: length += 1 if type(value) is list: res = value elif type(value) in [str, unicode]: if self.type == SwapType.NUMBER: try: # Possible integer number res = int(value) except ValueError: try: # Possible float number res = float(value) except ValueError: raise SwapException(value + " is not a valid numeric value for " + self.name) elif self.type == SwapType.BINARY: if value.lower() in ["on", "open", "1", "true", "enabled"]: res = 1 else: res = 0 else: # SwapType.STRING res = value else: res = value if type(res) in [int, float]: if self.unit is not None: res -= self.unit.offset res /= self.unit.factor # Take integer part only res = math.modf(res) swap_value = SwapValue(res, length) # Register value in list format lstRegVal = [] lstRegVal[:] = self.register.value.toList() # Build register value indexReg = self.bytePos shiftReg = 7 - self.bitPos # Total bits to be copied from this parameter bitsToCopy = self.byteSize * 8 + self.bitSize # Parameter value in list format lstParamVal = swap_value.toList() indexParam = 0 shiftParam = self.bitSize - 1 if shiftParam < 0: shiftParam = 7 for i in range(bitsToCopy): if (lstParamVal[indexParam] >> shiftParam) & 0x01 == 0: mask = ~(1 << shiftReg) lstRegVal[indexReg] &= mask else: mask = 1 << shiftReg lstRegVal[indexReg] |= mask shiftReg -= 1 shiftParam -= 1 # Register byte over? if shiftReg < 0: indexReg += 1 shiftReg = 7 # Parameter byte over? if shiftParam < 0: indexParam += 1 shiftParam = 7 # Convert to SWapValue newRegVal = SwapValue(lstRegVal) # Send SWAP command return self.register.sendSwapCmd(newRegVal)
def aes_encryption(self, password, decrypt=False): """ Encrypt/Decrypt packet using the Smart Encryption mechanism @param password: Smart Encryption password @param decrypt: Decrypt packet if True. Encrypt otherwise """ # Update password SwapPacket.aes_encrypt_pwd = password # Data length data_length = len(self.data[4:]) # Data in binary format data = self.data[4:] # Data in binary string format strdata = ''.join([chr(item) for item in self.data[4:]]) # Number of iterations loops = data_length / 16 if data_length % 16: loops += 1 # Create initial nonce init_nonce = [] for i in range(0, 4): for j in range(0, 4): init_nonce.append(self.data[j]) # Password in binary string format strpwd = ''.join([chr(item) for item in password.data]) encryptor = AES.new(strpwd) for i in range(0, loops): str_nonce = ''.join([chr(item) for item in init_nonce]) encrypted_count = encryptor.encrypt(str_nonce) # XOR encypted count against data for j in range(0, 16): k = j + i * 16 if k < data_length: data[k] ^= ord(encrypted_count[j]) else: break # Increment nonce init_nonce[-1] += 1 # Update raw data self.data[4:] = data if not decrypt: # Update packet fields self.function = data[0] & 0x7F if self.extended_address: self.srcAddress = (data[1] << 8) | data[2] self.regAddress = (data[3] << 8) | data[4] self.regId = data[5] if len(data[6:]) > 0: self.value = SwapValue(data[6:]) else: self.regAddress = data[1] self.regId = data[2] if len(data[3:]) > 0: self.value = SwapValue(data[3:])
def __init__(self, ccPacket=None, destAddr=SwapAddress.BROADCAST_ADDR, hop=0, nonce=0, function=SwapFunction.STATUS, regAddr=0, regId=0, value=None, extended_addr=False): """ Class constructor @param ccPacket: Raw CcPacket where to take the information from @param destAddr: Destination address @param hop: Transmission hop count @param nonce: Security nonce @param function: SWAP function code (see SwapDefs.SwapFunction for more details) @param regAddr: Register address (address of the mote where the register really resides) @param regId: Register ID @param value: Register value """ CcPacket.__init__(self) ## Extended address disabled by default self.extended_address = extended_addr ## Destination address self.destAddress = destAddr ## Source address self.srcAddress = regAddr ## Hop count for repeating purposes self.hop = hop ## Security option self.security = 0 ## Security nonce self.nonce = nonce ## Function code self.function = function ## Register address self.regAddress = regAddr ## Register ID self.regId = regId ## SWAP value self.value = value if ccPacket is not None: if len(ccPacket.data) < 7: raise SwapException("Packet received is too short") # Hop count for repeating purposes self.hop = (ccPacket.data[2] >> 4) & 0x0F # Security option self.security = ccPacket.data[2] & 0x0F # Security nonce self.nonce = ccPacket.data[3] # Superclass attributes ## RSSI byte self.rssi = ccPacket.rssi ## LQI byte self.lqi = ccPacket.lqi ## CcPacket data field self.data = ccPacket.data # Smart Encryption enabled? if self.security & 0x02 and SwapPacket.smart_encrypt_pwd is not None: # Decrypt packet self.smart_encryption(SwapPacket.smart_encrypt_pwd, decrypt=True) # AES-128 Encryption enabled? elif self.security & 0x04 and SwapPacket.aes_encrypt_pwd is not None: # Decrypt packet self.aes_encryption(SwapPacket.aes_encrypt_pwd, decrypt=True) elif self.security & 0x06: return # Function code self.function = ccPacket.data[4] & 0x7F # Extended address indicator self.extended_address = (ccPacket.data[4] & 0x80) != 0 if self.extended_address: # Destination address self.destAddress = (ccPacket.data[0] << 8) | ccPacket.data[1] # Source address self.srcAddress = (ccPacket.data[5] << 8) | ccPacket.data[6] # Register address self.regAddress = (ccPacket.data[7] << 8) | ccPacket.data[8] # Register ID self.regId = ccPacket.data[9] # Register value if len(ccPacket.data) >= 11: self.value = SwapValue(ccPacket.data[10:]) else: # Destination address self.destAddress = ccPacket.data[0] # Source address self.srcAddress = ccPacket.data[1] # Register address self.regAddress = ccPacket.data[5] # Register ID self.regId = ccPacket.data[6] # Register value if len(ccPacket.data) >= 8: self.value = SwapValue(ccPacket.data[7:]) else: self._update_ccdata()