示例#1
0
    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()
示例#2
0
    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()
示例#3
0
    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, SwapType.BSTRING
                    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()
示例#4
0
    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()
示例#5
0
 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)
示例#6
0
 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)
示例#7
0
 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)
示例#8
0
 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)
示例#9
0
 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)
示例#10
0
 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)
示例#11
0
 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)
示例#12
0
 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)
示例#13
0
 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)
示例#14
0
    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()
示例#15
0
    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()
示例#16
0
class SwapParam:
    """
    Generic SWAP parameter, integrated into a SWAP register
    """
    def getRegAddress(self):
        """
        Return register address of the current parameter
        
        @return Register address
        """
        return self.register.getAddress()


    def getRegId(self):
        """
        Return register ID of the current parameter
        
        @return Register ID
        """
        return self.register.id
    
    
    def update(self):
        """
        Update parameter's value, posibly after a change in its parent register
        """
        self.valueChanged = False
        if self.register is None:
            raise SwapException("Register not specified for current endpoint")
            return

        # Current register value converted to list
        lstRegVal = self.register.value.toList()
        # Total bits to be copied
        indexReg = self.bytePos
        shiftReg = 7 - self.bitPos
        bitsToCopy = self.byteSize * 8 + self.bitSize
        # Current parameter value in list format
        lstParamVal = self.value.toList()

        if len(lstParamVal) == 0:
            return

        # Keep old value
        oldParamVal = self.value.clone()
        indexParam = 0
        shiftParam = self.bitSize - 1

        if shiftParam < 0:
            shiftParam = 7
        for i in range(bitsToCopy):
            if indexReg >= len(lstRegVal):
                break            
            if (lstRegVal[indexReg] >> shiftReg) & 0x01 == 0:
                mask = ~(1 << shiftParam)
                lstParamVal[indexParam] &= mask
            else:
                mask = 1 << shiftParam
                lstParamVal[indexParam] |= 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

        # Did the value change?
        if not self.value.isEqual(oldParamVal):
            self.valueChanged = True
            
        # Update time stamp
        self.lastupdate = time.time()


    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 getValueInAscii(self):
        """
        Return value in ASCII string format
        
        @return Value in ASCII format
        """
        if self.type == SwapType.NUMBER:
            val = self.value.toInteger()
            # Add units
            if self.unit is not None:                
                if self.unit.calc is not None:
                    oper = self.unit.calc.replace("${val}", str(val))
                    try:    
                        val = eval("math." + oper)
                    except ValueError as ex:
                        raise SwapException("Math exception for " + oper + ". " + str(ex))
                                         
                strVal = str(val * self.unit.factor + self.unit.offset)
            else:
                strVal = str(val)
        elif self.type == SwapType.BINARY:
            strVal = self.value.toAscii()
            if strVal == "1":
                strVal = "on"
            elif strVal == "0":
                strVal = "off"
        else:
            strVal = self.value.toAsciiStr()
        
        return strVal
    
    
    def setUnit(self, strunit):
        """
        Set unit for the current parameter
        
        @param strunit: new unit in string format
        """
        if self.lstunits is None:
            raise SwapException("Parameter " + self.name + " does not support units")
        
        for unit in self.lstunits:
            if unit.name == strunit:
                self.unit = unit
                return
            
        raise SwapException("Unit " + strunit + " not found")
    
    
    def __init__(self, register=None, pType=SwapType.NUMBER, direction=SwapType.INPUT, name="", position="0", size="1", default=None, verif=None, units=None):
        """
        Class constructor

        @param register: Register containing this parameter
        @param pType: Type of SWAP endpoint (see SwapDefs.SwapType)
        @param direction: Input or output (see SwapDefs.SwapType)
        @param name: Short description about the parameter
        @param position: Position in bytes.bits within the parent register
        @param size: Size in bytes.bits
        @param default: Default value in string format
        @param verif: Verification string
        @param units: List of units
        """
        ## Parameter name
        self.name = name
        ## Register where the current parameter belongs to
        self.register = register
             
        ## Data type (see SwapDefs.SwapType for more details)
        self.type = pType       
        ## Direction (see SwapDefs.SwapType for more details)
        self.direction = direction
        ## Position (in bytes) of the parameter within the register
        self.bytePos = 0
        ## Position (in bits) after bytePos
        self.bitPos = 0
        # Get true positions
        dot = position.find('.')
        if dot > -1:
            self.bytePos = int(position[:dot])
            self.bitPos = int(position[dot+1:])
        else:
            self.bytePos = int(position)

        ## Size (in bytes) of the parameter value
        self.byteSize = 1
        ## Size in bits of the parameter value after byteSize
        self.bitSize = 0
        # Get true sizes
        dot = size.find('.')
        if dot > -1:
            self.byteSize = int(size[:dot])
            self.bitSize = int(size[dot+1:])
        else:
            self.byteSize = int(size)

        ## Current value
        self.value = None
        ## Time stamp of the last update
        self.lastupdate = None
        
        ## List of units
        self.lstunits = units
        ## Selected unit
        self.unit = None
        if self.lstunits is not None and len(self.lstunits) > 0:
            self.unit = self.lstunits[0]

        # Set initial value
        if default is not None:
            self.setValue(default)

        ## Flag that tells us whether this parameter changed its value during the last update or not
        self.valueChanged = False
        
        ## Verification string. This can be a macro or a regular expression
        self.verif = verif
        
        ## Display this parameter from master app
        self.display = True
示例#17
0
    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)
示例#18
0
class SwapPacket(CcPacket):
    """
    SWAP packet class
    """
    smart_encrypt_pwd = None
    aes_encrypt_pwd = None

    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 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 send(self, server):
        """
        Overriden send method
        
        @param server: SWAP server object to be used for transmission
        """
        self.srcAddress = server.devaddress
        self.data[1] = self.srcAddress

        # Update security option according to server's one
        self.security = server.security
        self.data[2] |= self.security & 0x0F

        # Keep copy of the current packet before encryption
        packet_before_encrypt = copy.copy(self)

        # Smart encryption enabled?
        if self.security & 0x02:
            # Encrypt packet
            self.smart_encryption(server.password)
        # AES-128 encryption enabled?
        elif self.security & 0x04:
            # Encrypt packet
            self.aes_encryption(server.password)

        CcPacket.send(self, server.modem)
        # Notify event
        server._eventHandler.swapPacketSent(packet_before_encrypt)

    def _update_ccdata(self):
        """
        Update ccPacket data bytes
        """
        self.data = []

        if self.extended_address:
            """
            self.data[0] = (self.destAddress >> 8) & 0x0F
            self.data[1] = self.destAddress & 0x0F
            self.data[5] = (self.srcAddress >> 8) & 0x0F
            self.data[6] = self.srcAddress & 0x0F
            self.data[7] = (self.regAddress >> 8) & 0x0F
            self.data[8] = self.regAddress & 0x0F
            self.data[9] = self.regId
            """
            self.data.append((self.destAddress >> 8) & 0x0F)
            self.data.append(self.destAddress & 0x0F)

            self.data.append((self.hop << 4) | (self.security & 0x0F))
            self.data.append(self.nonce)
            self.data.append(self.function | (self.extended_address * (0x80)))

            self.data.append((self.srcAddress >> 8) & 0x0F)
            self.data.append(self.srcAddress & 0x0F)
            self.data.append((self.regAddress >> 8) & 0x0F)
            self.data.append(self.regAddress & 0x0F)
            self.data.append(self.regId)
        else:
            """
            self.data[0] = self.destAddress
            self.data[1] = self.srcAddress
            self.data[5] = self.srcAddress
            self.data[6] = self.regId
            """

            self.data.append(self.destAddress)
            self.data.append(self.srcAddress)
            self.data.append((self.hop << 4) | (self.security & 0x0F))
            self.data.append(self.nonce)
            self.data.append(self.function | (self.extended_address * (0x80)))
            self.data.append(self.srcAddress)
            self.data.append(self.regId)
        """
        self.data[2] = (self.hop << 4) | (self.security & 0x0F)
        self.data[3] = self.nonce
        self.data[4] = self.function | (self.extended_address * (0x80))       
        """

        if self.value is not None:
            for item in self.value.toList():
                self.data.append(item)

    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()
示例#19
0
    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:])
示例#20
0
class SwapPacket(CcPacket):
    """
    SWAP packet class
    """
    smart_encrypt_pwd = None
    aes_encrypt_pwd = None

    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 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 send(self, server):
        """
        Overriden send method
        
        @param server: SWAP server object to be used for transmission
        """
        self.srcAddress = server.devaddress
        self.data[1] = self.srcAddress
        
        # Update security option according to server's one
        self.security = server.security
        self.data[2] |= self.security & 0x0F

        # Keep copy of the current packet before encryption
        packet_before_encrypt = copy.copy(self)
        
        # Smart encryption enabled?
        if self.security & 0x02:
            # Encrypt packet
            self.smart_encryption(server.password)
        # AES-128 encryption enabled?
        elif self.security & 0x04:
            # Encrypt packet
            self.aes_encryption(server.password)
        
        CcPacket.send(self, server.modem)
        # Notify event        
        server._eventHandler.swapPacketSent(packet_before_encrypt)
        
        
    def _update_ccdata(self):
        """
        Update ccPacket data bytes
        """
        self.data = []
        
        if self.extended_address:
            """
            self.data[0] = (self.destAddress >> 8) & 0x0F
            self.data[1] = self.destAddress & 0x0F
            self.data[5] = (self.srcAddress >> 8) & 0x0F
            self.data[6] = self.srcAddress & 0x0F
            self.data[7] = (self.regAddress >> 8) & 0x0F
            self.data[8] = self.regAddress & 0x0F
            self.data[9] = self.regId
            """
            self.data.append((self.destAddress >> 8) & 0x0F)
            self.data.append(self.destAddress & 0x0F)
            
            self.data.append((self.hop << 4) | (self.security & 0x0F))
            self.data.append(self.nonce)
            self.data.append(self.function | (self.extended_address * (0x80)))
            
            self.data.append((self.srcAddress >> 8) & 0x0F)
            self.data.append(self.srcAddress & 0x0F)
            self.data.append((self.regAddress >> 8) & 0x0F)
            self.data.append(self.regAddress & 0x0F)
            self.data.append(self.regId)
        else:
            """
            self.data[0] = self.destAddress
            self.data[1] = self.srcAddress
            self.data[5] = self.srcAddress
            self.data[6] = self.regId
            """

            self.data.append(self.destAddress)
            self.data.append(self.srcAddress)       
            self.data.append((self.hop << 4) | (self.security & 0x0F))
            self.data.append(self.nonce)
            self.data.append(self.function | (self.extended_address * (0x80)))
            self.data.append(self.srcAddress)
            self.data.append(self.regId)
            
        """
        self.data[2] = (self.hop << 4) | (self.security & 0x0F)
        self.data[3] = self.nonce
        self.data[4] = self.function | (self.extended_address * (0x80))       
        """
        
        if self.value is not None:
            for item in self.value.toList():
                self.data.append(item)


    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()
示例#21
0
    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:])
示例#22
0
class SwapParam:
    """
    Generic SWAP parameter, integrated into a SWAP register
    """
    def getRegAddress(self):
        """
        Return register address of the current parameter
        
        @return Register address
        """
        return self.register.getAddress()


    def getRegId(self):
        """
        Return register ID of the current parameter
        
        @return Register ID
        """
        return self.register.id
    
    
    def update(self):
        """
        Update parameter's value, posibly after a change in its parent register
        """
        self.valueChanged = False
        if self.register is None:
            raise SwapException("Register not specified for current endpoint")
            return

        # Keep old value
        oldParamVal = self.value.clone()
        
        # This is a particular case: endpoint is an ASCII string taking all the
        # register space
        if self.type in [SwapType.STRING, SwapType.BSTRING]:
            self.value = self.register.value
        else:
            # Current register value converted to list
            lstRegVal = self.register.value.toList()
            # Total bits to be copied
            indexReg = self.bytePos
            shiftReg = 7 - self.bitPos
            bitsToCopy = self.byteSize * 8 + self.bitSize
            # Current parameter value in list format
            lstParamVal = self.value.toList()
    
            if len(lstParamVal) == 0:
                return
    
            indexParam = 0
            shiftParam = self.bitSize - 1
    
            if shiftParam < 0:
                shiftParam = 7
            for i in range(bitsToCopy):
                if indexReg >= len(lstRegVal):
                    break            
                if (lstRegVal[indexReg] >> shiftReg) & 0x01 == 0:
                    mask = ~(1 << shiftParam)
                    lstParamVal[indexParam] &= mask
                else:
                    mask = 1 << shiftParam
                    lstParamVal[indexParam] |= 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
    
        # Did the value change?
        if not self.value.isEqual(oldParamVal):
            self.valueChanged = True
            
        # Update time stamp
        self.lastupdate = time.time()


    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, SwapType.BSTRING
                    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 getValueInAscii(self):
        """
        Return value in ASCII string format
        
        @return Value in ASCII format
        """
        if self.type == SwapType.NUMBER:
            val = self.value.toInteger()
            # Add units
            if self.unit is not None:                
                if self.unit.calc is not None:
                    oper = self.unit.calc.replace("${val}", str(val))
                    try:    
                        val = eval("math." + oper)
                    except ValueError as ex:
                        raise SwapException("Math exception for " + oper + ". " + str(ex))
                                         
                strVal = str(val * self.unit.factor + self.unit.offset)
            else:
                strVal = str(val)
        elif self.type == SwapType.BINARY:
            strVal = self.value.toAscii()
            if strVal == "1":
                strVal = "on"
            elif strVal == "0":
                strVal = "off"
        elif self.type == SwapType.BSTRING:
            strVal = self.value.toAsciiHex()
        else:
            strVal = self.value.toAsciiStr()
        
        return strVal
    
    
    def setUnit(self, strunit):
        """
        Set unit for the current parameter
        
        @param strunit: new unit in string format
        """
        if self.lstunits is None:
            raise SwapException("Parameter " + self.name + " does not support units")
        
        for unit in self.lstunits:
            if unit.name == strunit:
                self.unit = unit
                return
            
        raise SwapException("Unit " + strunit + " not found")
    
    
    def __init__(self, register=None, pType=SwapType.NUMBER, direction=SwapType.INPUT, name="", position="0", size="1", default=None, verif=None, units=None):
        """
        Class constructor

        @param register: Register containing this parameter
        @param pType: Type of SWAP endpoint (see SwapDefs.SwapType)
        @param direction: Input or output (see SwapDefs.SwapType)
        @param name: Short description about the parameter
        @param position: Position in bytes.bits within the parent register
        @param size: Size in bytes.bits
        @param default: Default value in string format
        @param verif: Verification string
        @param units: List of units
        """
        ## Parameter name
        self.name = name
        ## Register where the current parameter belongs to
        self.register = register
             
        ## Data type (see SwapDefs.SwapType for more details)
        self.type = pType       
        ## Direction (see SwapDefs.SwapType for more details)
        self.direction = direction
        ## Position (in bytes) of the parameter within the register
        self.bytePos = 0
        ## Position (in bits) after bytePos
        self.bitPos = 0
        # Get true positions
        dot = position.find('.')
        if dot > -1:
            self.bytePos = int(position[:dot])
            self.bitPos = int(position[dot+1:])
        else:
            self.bytePos = int(position)

        ## Size (in bytes) of the parameter value
        self.byteSize = 1
        ## Size in bits of the parameter value after byteSize
        self.bitSize = 0
        # Get true sizes
        dot = size.find('.')
        if dot > -1:
            self.byteSize = int(size[:dot])
            self.bitSize = int(size[dot+1:])
        else:
            self.byteSize = int(size)

        ## Current value
        self.value = None
        ## Time stamp of the last update
        self.lastupdate = None
        
        ## List of units
        self.lstunits = units
        ## Selected unit
        self.unit = None
        if self.lstunits is not None and len(self.lstunits) > 0:
            self.unit = self.lstunits[0]

        # Set initial value
        if default is not None:
            self.setValue(default)

        ## Flag that tells us whether this parameter changed its value during the last update or not
        self.valueChanged = False
        
        ## Verification string. This can be a macro or a regular expression
        self.verif = verif
        
        ## Display this parameter from master app
        self.display = True
示例#23
0
    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
        """
        # This is a particular case: endpoint is an ASCII string taking all the
        # register space
        if self.type == SwapType.STRING and type(value) in [str, unicode]:
            lstRegVal = value
        else:
            # 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, SwapType.BSTRING
                        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)
示例#24
0
class SwapPacket(CcPacket):
    """
    SWAP packet class
    """
    smart_encrypt_pwd = None

    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 send(self, server):
        """
        Overriden send method
        
        @param server: SWAP server object to be used for transmission
        """
        self.srcAddress = server.devaddress
        self.data[1] = self.srcAddress
        
        # Update security option according to server's one
        self.security = server.security
        self.data[2] |= self.security & 0x0F

        # Keep copy of the current packet before encryption
        packet_before_encrypt = copy.copy(self)
        
        # Smart encryption enabled?
        if self.security & 0x02:
            # Encrypt packet
            self.smart_encryption(server.password)
        
        CcPacket.send(self, server.modem)
        # Notify event        
        server._eventHandler.swapPacketSent(packet_before_encrypt)
        
        
    def _update_ccdata(self):
        """
        Update ccPacket data bytes
        """
        self.data = []

        self.data.append(self.destAddress)
        self.data.append(self.srcAddress)
        self.data.append((self.hop << 4) | (self.security & 0x0F))
        self.data.append(self.nonce)
        self.data.append(self.function)
        self.data.append(self.regAddress)
        self.data.append(self.regId)

        if self.value is not None:
            for item in self.value.toList():
                self.data.append(item)


    def __init__(self, ccPacket=None, destAddr=SwapAddress.BROADCAST_ADDR, hop=0, nonce=0, function=SwapFunction.STATUS, regAddr=0, regId=0, value=None):
        """
        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)

        ## 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")
            # Superclass attributes
            ## RSSI byte
            self.rssi = ccPacket.rssi
            ## LQI byte
            self.lqi = ccPacket.lqi
            ## CcPacket data field
            self.data = ccPacket.data
            # Destination address
            self.destAddress = ccPacket.data[0]
            # Source address
            self.srcAddress = ccPacket.data[1]
            # 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]
            # Function code
            self.function = ccPacket.data[4]
            # Register address
            self.regAddress = ccPacket.data[5]
            # Register ID
            self.regId = ccPacket.data[6]
                       
            if len(ccPacket.data) >= 8:
                self.value = SwapValue(ccPacket.data[7:])   
            # 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)
        
        else:
            self._update_ccdata()