def parseErrorState(self, meshErrorState):
        self.crownstoneId = meshErrorState[0]
        self.hasError = True
        self.errorMode = True
        
        self.errorsBitmask = Conversion.uint8_array_to_uint32([
            meshErrorState[1],
            meshErrorState[2],
            meshErrorState[3],
            meshErrorState[4]
        ])
        
        self.errorTimestamp = Conversion.uint8_array_to_uint32([
            meshErrorState[5],
            meshErrorState[6],
            meshErrorState[7],
            meshErrorState[8]
        ])
        
        self.flagsBitmask = meshErrorState[9]
        self.temperature = meshErrorState[10]

        self.partialTimestamp = Conversion.uint8_array_to_uint16(meshErrorState[11:13])
        self.timestamp = reconstructTimestamp(time.time(), self.partialTimestamp)
    
        if self.crownstoneId == 0:
            self.deprecated = True
Esempio n. 2
0
 def _verifyDecryption(decrypted, validationKey):
     # the conversion to uint32 only takes the first 4 bytes
     if Conversion.uint8_array_to_uint32(decrypted) == Conversion.uint8_array_to_uint32(validationKey):
         # remove checksum from decryption and return payload
         result = [0] * (len(decrypted) - SESSION_KEY_LENGTH)
         for i in range(0,len(result)):
             result[i] = decrypted[i+SESSION_KEY_LENGTH]
         return result
 
     else:
         raise BluenetBleException(BleError.ENCRYPTION_VALIDATION_FAILED, "Failed to validate result, Could not decrypt")
Esempio n. 3
0
def parseOpCode3_type1(serviceData, data):
    if len(data) == 17:
        # opCode = data[0]
        # dataType = data[1]
        
        serviceData.errorMode = True
        
        serviceData.crownstoneId = data[2]
        serviceData.errorsBitmask = Conversion.uint8_array_to_uint32([
            data[3],
            data[4],
            data[5],
            data[6]
        ])
        
        serviceData.errorTimestamp = Conversion.uint8_array_to_uint32([
            data[7],
            data[8],
            data[9],
            data[10]
        ])
        
        serviceData.flagsBitmask = data[11]
        # bitmask states
        bitmaskArray = Conversion.uint8_to_bit_array(serviceData.flagsBitmask)
        
        serviceData.dimmingAvailable   = bitmaskArray[0]
        serviceData.dimmingAllowed     = bitmaskArray[1]
        serviceData.hasError           = bitmaskArray[2]
        serviceData.switchLocked       = bitmaskArray[3]
        serviceData.timeIsSet          = bitmaskArray[4]
        serviceData.switchCraftEnabled = bitmaskArray[5]
        
        serviceData.temperature = Conversion.uint8_to_int8(data[12])

        serviceData.partialTimestamp = Conversion.uint8_array_to_uint16([data[13], data[14]])
        serviceData.uniqueIdentifier = serviceData.partialTimestamp

        if serviceData.timeIsSet:
            serviceData.timestamp = reconstructTimestamp(time.time(), serviceData.partialTimestamp)
        else:
            serviceData.timestamp = serviceData.partialTimestamp # this is now a counter
        
        realPower = Conversion.uint16_to_int16(
            Conversion.uint8_array_to_uint16([
                data[15],
                data[16]
            ])
        )
        
        serviceData.powerUsageReal = float(realPower) / 8.0
        
        # this packet has no validation
        serviceData.validation = 0
Esempio n. 4
0
    def __init__(self, payload):
        self.stoneStates = []

        if len(payload) != MESH_STATE_PACKET_SIZE:
            print("ERROR: INVALID PAYLOAD LENGTH", len(payload), payload)
            return
        self.stoneStates = []
        self.head = payload[0]
        self.tail = payload[1]
        self.size = payload[2]
        self.timestamp = Conversion.uint8_array_to_uint32(payload[4:8])

        expectedSizeOfStoneStates = self.size * STONE_STATE_PACKET_SIZE

        if expectedSizeOfStoneStates + 8 > MESH_STATE_PACKET_SIZE:
            print("ERROR: CANT FIT STONE STATE PACKETS IN MESSAGE",
                  expectedSizeOfStoneStates)
            return

        for i in range(0, self.size):
            self.stoneStates.append(
                StoneStatePacket(payload[8 + i * STONE_STATE_PACKET_SIZE:8 +
                                         (i + 1) * STONE_STATE_PACKET_SIZE]))

        # deprecation is when a stone id has multiple entrees in the data. Checking for this makes sure we only use the latest one.
        self._checkForDeprecation()
Esempio n. 5
0
def obtainTimestamp(fullTimeStamp, lsb):
    timestampBytes = Conversion.uint32_to_uint8_array(int(fullTimeStamp))
    lsbBytes = Conversion.uint16_to_uint8_array(lsb)

    restoredTimestamp = Conversion.uint8_array_to_uint32(
        [lsbBytes[0], lsbBytes[1], timestampBytes[2], timestampBytes[3]])

    return restoredTimestamp
Esempio n. 6
0
def parseOpCode3_type0(serviceData, data):
    if len(data) == 16:
        # dataType = data[0]

        serviceData.stateOfExternalCrownstone = False

        serviceData.crownstoneId = data[1]
        serviceData.switchState = data[2]
        serviceData.flagsBitmask = data[3]

        # bitmask states
        bitmaskArray = Conversion.uint8_to_bit_array(serviceData.flagsBitmask)

        serviceData.dimmerReady = bitmaskArray[0]
        serviceData.dimmingAllowed = bitmaskArray[1]
        serviceData.hasError = bitmaskArray[2]
        serviceData.switchLocked = bitmaskArray[3]
        serviceData.timeIsSet = bitmaskArray[4]
        serviceData.switchCraftEnabled = bitmaskArray[5]

        serviceData.tapToToggleEnabled = bitmaskArray[6]
        serviceData.behaviourOverridden = bitmaskArray[7]

        serviceData.temperature = Conversion.uint8_to_int8(data[4])
        powerFactor = Conversion.uint8_to_int8(data[5])
        realPower = Conversion.uint16_to_int16(
            Conversion.uint8_array_to_uint16([data[6], data[7]]))

        serviceData.powerFactor = float(powerFactor) / 127.0

        # we cannot have a 0 for a power factor.To avoid division by 0, we set it to be either 0.01 or -0.01
        if 0 <= serviceData.powerFactor < 0.01:
            serviceData.powerFactor = 0.01
        elif -0.01 < serviceData.powerFactor < 0:
            serviceData.powerFactor = -0.01

        serviceData.powerUsageReal = float(realPower) / 8.0
        serviceData.powerUsageApparent = serviceData.powerUsageReal / serviceData.powerFactor

        serviceData.accumulatedEnergy = Conversion.uint32_to_int32(
            Conversion.uint8_array_to_uint32(
                [data[8], data[9], data[10], data[11]]))

        serviceData.partialTimestamp = Conversion.uint8_array_to_uint16(
            [data[12], data[13]])
        serviceData.uniqueIdentifier = serviceData.partialTimestamp

        if serviceData.timeIsSet:
            serviceData.timestamp = reconstructTimestamp(
                time.time(), serviceData.partialTimestamp)
        else:
            serviceData.timestamp = serviceData.partialTimestamp  # this is now a counter

        globalBitmaskArray = Conversion.uint8_to_bit_array(data[14])
        serviceData.behaviourEnabled = globalBitmaskArray[0]

        serviceData.validation = data[15]
 def __init__(self, payload, channelIndex):
     if len(payload) < self.packetSize:
         print("ERROR: INVALID PAYLOAD LENGTH", len(payload), payload)
         return
     
     self.channelIndex = channelIndex
     
     self.pin    = payload[0]
     self.range  = Conversion.uint8_array_to_uint32(payload[1:1+4])
     self.refPin = payload[5]
    def __init__(self, payload):
        if len(payload) < self.packetSize:
            print("ERROR: INVALID PAYLOAD LENGTH", len(payload), payload)
            return

        self.timestampCounter = Conversion.uint8_array_to_uint32(payload[0:4])
        self.samples = []
        for i in range(4, self.packetSize, self.sampleSize):
            self.samples.append(
                Conversion.uint8_array_to_int16(payload[i:i +
                                                        self.sampleSize]))
Esempio n. 9
0
 def decryptSessionNonce(inputData, key):
     if len(inputData) == 16:
         decrypted = EncryptionHandler.decryptECB(inputData, key)
         checksum = Conversion.uint8_array_to_uint32(decrypted)
         if checksum == CHECKSUM:
             return [decrypted[4], decrypted[5], decrypted[6], decrypted[7], decrypted[8]]
         else:
             raise BluenetBleException(BleError.COULD_NOT_VALIDATE_SESSION_NONCE, "Could not validate the session nonce.")
 
     else:
         raise BluenetBleException(BleError.COULD_NOT_READ_SESSION_NONCE, "Could not read session nonce, maybe encryption is disabled?")
Esempio n. 10
0
    def generateMeshAccessAddress(retries=0):
        randomArray = [
            random.randint(0, 255),
            random.randint(0, 255),
            random.randint(0, 255),
            random.randint(0, 255)
        ]
        if not Util.validateMeshAccessAddress(randomArray) and retries < 100:
            retries += 1
            return Util.generateMeshAccessAddress(retries)

        return Conversion.uint8_array_to_uint32(randomArray)
Esempio n. 11
0
def parseOpcode4_type0(serviceData, data):
    if len(data) == 17:
        # opCode   = data[0]
        # dataType = data[1]

        serviceData.switchState  = data[2]
        serviceData.flagsBitmask = data[3]
        
        # bitmask states
        bitmaskArray                 = Conversion.uint8_to_bit_array(serviceData.flagsBitmask)
        serviceData.dimmingAvailable = bitmaskArray[0]
        serviceData.dimmingAllowed   = bitmaskArray[1]
        serviceData.hasError         = bitmaskArray[2]
        serviceData.switchLocked     = bitmaskArray[3]
        serviceData.timeIsSet        = bitmaskArray[4]
        
        serviceData.temperature  = Conversion.uint8_to_int8(data[4])
        
        powerFactor = Conversion.uint8_to_int8(data[5])
        realPower = Conversion.uint16_to_int16(Conversion.uint8_array_to_uint16([data[6], data[7]]))

        serviceData.powerFactor = float(powerFactor) / 127.0
        
        # we cannot have a 0 for a power factor.To avoid division by 0, we set it to be either 0.01 or -0.01
        if 0 <= serviceData.powerFactor < 0.01:
            serviceData.powerFactor = 0.01
        elif -0.01 < serviceData.powerFactor < 0:
            serviceData.powerFactor = -0.01

        
        serviceData.powerUsageReal = float(realPower) / 8.0
        serviceData.powerUsageApparent = serviceData.powerUsageReal / serviceData.powerFactor
        
        serviceData.accumulatedEnergy = Conversion.uint32_to_int32(
            Conversion.uint8_array_to_uint32([
                data[8],
                data[9],
                data[10],
                data[11]
            ])
        )
    
        serviceData.uniqueIdentifier = data[12]
    def __init__(self, payload):
        if len(payload) < 1:
            print("ERROR: INVALID PAYLOAD LENGTH", len(payload), payload)
            return

        index = 0
        self.amountOfChannels = payload[index]
        index += 1
        self.packetSize = self.amountOfChannels * self.channelSize + 1 + 4  # 4 for sampling period, 1 for count

        if len(payload) < self.packetSize:
            print("ERROR: INVALID PAYLOAD LENGTH", len(payload), payload)
            return

        for i in range(0, self.amountOfChannels):
            self.channels.append(
                AdcChannelPacket(payload[index:index + self.channelSize], i))
            index += self.channelSize

        self.samplingPeriod = Conversion.uint8_array_to_uint32(
            payload[index:index + 4])
Esempio n. 13
0
    def validateMeshAccessAddress(randomArray):
        address = Conversion.uint8_array_to_uint32(randomArray)
        bitArray = Conversion.uint32_to_bit_array(address)
        bitArrayAdvertising = Conversion.uint32_to_bit_array(
            ADVERTISING_ACCESS_ADDRESS)

        # Requirement: It shall not be the advertising channel packets’ Access Address.
        if address == ADVERTISING_ACCESS_ADDRESS:
            # print("1")
            return False

        # Requirement: It shall not have all four octets equal.
        if randomArray[0] == randomArray[1] and randomArray[0] == randomArray[
                2] and randomArray[0] == randomArray[3]:
            # print("2")
            return False

        # Requirement: It shall not be a sequence that differs from the advertising channel packets’ Access Address by only one bit.
        diffCount = 0
        for idx, bit in enumerate(bitArray):
            if bit != bitArrayAdvertising[idx]:
                diffCount += 1

            if diffCount > 1:
                break

        if diffCount <= 1:
            # print("3")
            return False

        # Requirement: It shall have no more than six consecutive zeros or ones.
        consZero = 0
        consOne = 0
        for bit in bitArray:
            if bit:
                consOne += 1
                consZero = 0
            else:
                consZero += 1
                consOne = 0

            if consOne > 5 or consZero > 5:
                break

        if consOne > 5 or consZero > 5:
            # print("4")
            return False

        # Requirement: It shall have no more than 24 transitions.
        transitions = 0
        for i in range(1, len(bitArray)):
            if bitArray[i] != bitArray[i - 1]:
                transitions += 1

        if transitions > 24:
            # print("5")
            return False

        # Requirement: It shall have a minimum of two transitions in the most significant six bits.
        transitions = 0
        for i in range(1, 6):
            if bitArray[i] != bitArray[i - 1]:
                transitions += 1

        if transitions < 2:
            # print("6")
            return False

        transitions = 0
        for i in range(len(bitArray) - 5, len(bitArray)):
            if bitArray[i] != bitArray[i - 1]:
                transitions += 1

        if transitions < 2:
            # print("7")
            return False

        return True
Esempio n. 14
0
 def getUInt32(self):
     return Conversion.uint8_array_to_uint32(self._request(4))
Esempio n. 15
0
 def getTime(self):
     bytesResult = self._getState(StateType.TIME)
     return Conversion.uint8_array_to_uint32(bytesResult)