encoder now adds preamble.
lecacy.py now uses new C radio driver
1 parent 9c021dd commit f61c30874adcce235ceaf74bd92c0dc6f1426b3f
@David Whale David Whale authored on 16 Apr 2016
Showing 3 changed files
View
168
src/energenie/encoder.py
#
# payload encoder for use with OOK payloads
 
ALL_SOCKETS = 0
 
# The preamble is now stored in the payload,
# this is more predictable than using the radio sync feature
PREAMBLE = [0x80, 0x00, 0x00, 0x00]
 
# This generates a 20*4 bit address i.e. 10 bytes
# The number generated is always the same
# This is the random 'Energenie address prefix'
# The switch number is encoded in the payload
# 0000 00BA gets encoded as:
# 128 64 32 16 8 4 2 1
# 1 B B 0 1 A A 0
#payload = []
#for i in range(10):
# j = i + 5
# payload.append(8 + (j&1) * 6 + 128 + (j&2) * 48)
#dumpPayloadAsHex(payload)
 
#this is just a fixed address generator, from the C code
#payload = []
#for i in range(10):
# j = i + 5
# payload.append(8 + (j&1) * 6 + 128 + (j&2) * 48)
#dumpPayloadAsHex(payload)
# binary = 0110 1100 0110 1100 0110
# hex = 6 C 6 C 6
 
DEFAULT_ADDR = 0x6C6C6
 
# 5 6 7 8 9 10 11 12 13 14
# 1(01) 1(10) 1(11) 0(00) 0(01) 0(10) 0(11) 1(00) 1(01) 1(10)
DEFAULT_ADDR_ENC = [0x8e, 0xe8, 0xee, 0x88, 0x8e, 0xe8, 0xee, 0x88, 0x8e, 0xe8]
 
# D0=high, D1=high, D2-high, D3=high (S1 on) sent as:(D0D1D2D3)
# 128 64 32 16 8 4 2 1 128 64 32 16 8 4 2 1
# 1 B B 0 1 A A 0 1 B B 0 1 A A 0
# 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0
 
SW1_ON_ENC = [0xEE, 0xEE] # 1111 sent as 1111
 
# D0=high, D1=high, D2=high, D3=low (S1 off)
# 128 64 32 16 8 4 2 1 128 64 32 16 8 4 2 1
# 1 B B 0 1 A A 0 1 B B 0 1 A A 0
# 1 1 1 0 1 1 1 0 1 1 1 0 1 0 0 0
 
SW1_OFF_ENC = [0xEE, 0xE8] # 1110 sent as 0111
 
 
def ashex(payload):
line = ""
for b in payload:
 
def build_relay_msg(relayState=False):
"""Temporary test code to prove we can turn the relay on or off"""
 
# This generates a 20*4 bit address i.e. 10 bytes
# The number generated is always the same
# Presumably this is the random 'Energenie address prefix'
# The switch number is encoded in the payload
payload = PREAMBLE
 
# Looks like: 0000 00BA gets encoded as:
# 128 64 32 16 8 4 2 1
# 1 B B 0 1 A A 0
 
#payload = []
#for i in range(10):
# j = i + 5
# payload.append(8 + (j&1) * 6 + 128 + (j&2) * 48)
#dumpPayloadAsHex(payload)
#
# 5 6 7 8 9 10 11 12 13 14
# 1(01) 1(10) 1(11) 0(00) 0(01) 0(10) 0(11) 1(00) 1(01) 1(10)
payload = [0x8e, 0xe8, 0xee, 0x88, 0x8e, 0xe8, 0xee, 0x88, 0x8e, 0xe8]
 
#TODO: This is taken from the C code, it might be wrong
#(the D bit order seems reversed compared to the pdf spec)
if relayState: # ON
# D0=high, D1=high, D2-high, D3=high (S1 on)
# 128 64 32 16 8 4 2 1 128 64 32 16 8 4 2 1
# 1 B B 0 1 A A 0 1 B B 0 1 A A 0
# 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0
payload += [0xEE, 0xEE] # 1111
payload += SW1_ON_ENC
 
else: # OFF
# D0=high, D1=high, D2=high, D3=low (S1 off)
# 128 64 32 16 8 4 2 1 128 64 32 16 8 4 2 1
# 1 B B 0 1 A A 0 1 B B 0 1 A A 0
# 1 1 1 0 1 1 1 0 1 1 1 0 1 0 0 0
payload += [0xEE, 0xE8] # 1110
payload += SW1_OFF_ENC
 
return payload
 
 
def build_test_message(pattern):
payload = [0x8E, 0xE8, 0xEE, 0x88, 0x8E, 0xE8, 0xEE, 0x88, 0x8E, 0xE8]
"""build a test message for a D3D2D1D0 control patter"""
payload = PREAMBLE + DEFAULT_ADDR_ENC
pattern &= 0x0F
control = encode_bits(pattern, 4)
payload += control
return payload
"""Build a message to turn a switch on or off"""
#print("build: state:%s, device:%d, house:%s" % (str(state), device_address, str(house_address)))
 
if house_address == None:
#this is just a fixed address generator, from the C code
#payload = []
#for i in range(10):
# j = i + 5
# payload.append(8 + (j&1) * 6 + 128 + (j&2) * 48)
#dumpPayloadAsHex(payload)
# binary = 0110 1100 0110 1100 0110
# hex = 6 C 6 C 6
house_address = 0x6C6C6
house_address = DEFAULT_ADDR
 
payload = encode_bits((house_address & 0x0F0000) >> 16, 4)
payload = [] + PREAMBLE
payload += encode_bits((house_address & 0x0F0000) >> 16, 4)
payload += encode_bits((house_address & 0x00FF00) >> 8, 8)
payload += encode_bits((house_address & 0x0000FF), 8)
 
#TODO: D3210 are the other way round in the message??
#This is correct as presented by the PDF from Energenie though.
#the relay test code above proves that bit position 0 is the on/off command
#so the next 3 bits are just like extra address bits
# Turn switch request into a 4 bit switch command, and add to payload
# D 3210
# 0000 UNUSED
# 0001 UNUSED
# 0010 UNUSED
# 0011 All off (3)
# 0100 socket 4 off (4)
# 0101 socket 3 off (5)
# 0110 socket 2 off (6)
# 0111 socket 1 off (7)
# 1000 UNUSED
# 1001 UNUSED
# 1010 UNUSED
# 1011 All on (3)
# 1100 socket 4 on (4)
# 1101 socket 3 on (5)
# 1110 socket 2 on (6)
# 1111 socket 1 on (7)
 
# Coded as per the (working) C code would be:
# Coded as per the (working) C code, as it is transmitted D0D1D2D3:
# D 0123
# b 3210
# 0000 UNUSED 0
# 0001 UNUSED 1
# 0010 socket 4 off 2
elif device_address == 4:
bits |= 0x02
payload += encode_bits(bits, 4)
#print("encoded as:%s" % ashex(payload))
return payload
 
 
def encode_bytes(data):
bits = (data >> shift) & 0x03
#print(" shift %d bits %d" % (shift, bits))
encoded.append(ENCODER[bits])
shift -= 2
#print(" returns:%s" % ashex(modulated))
#print(" returns:%s" % ashex(encoded))
return encoded
 
 
# END
View
2
■■■
src/energenie/encoder_test.py
 
tests = [ALL_ON, ALL_OFF, ONE_ON, ONE_OFF, TWO_ON, TWO_OFF, THREE_ON, THREE_OFF, FOUR_ON, FOUR_OFF, MYHOUSE_ALL_ON]
 
for t in tests:
print('')
print(ashex(t))
 
# END
 
 
View
50
src/legacy.py
# completely verified.
 
import time
 
from energenie import encoder, radio
from energenie import encoder
# moving over to the new, faster, C radio driver
from energenie import radio2 as radio
 
# How many times to repeat messages
# Present version of driver limits to 8
# but this restriction will be lifted soon
REPEATS = 8
 
 
#----- TEST APPLICATION -------------------------------------------------------
 
if y:
print("Press the LEARN button on any switch %d for 5 secs until LED flashes" % switch_no)
raw_input("press ENTER when LED is flashing")
 
for i in range(8):
print("ON")
radio.transmit(ON_MSGS[switch_no])
time.sleep(1)
print("ON")
radio.send_payload(ON_MSGS[switch_no], REPEATS)
time.sleep(1)
 
print("Device should now be programmed")
print("Testing....")
for i in range(4):
time.sleep(1)
print("OFF")
radio.transmit(OFF_MSGS[switch_no])
radio.send_payload(OFF_MSGS[switch_no], REPEATS)
time.sleep(1)
print("ON")
radio.transmit(ON_MSGS[switch_no])
radio.send_payload(ON_MSGS[switch_no], REPEATS)
print("Test completed")
 
 
def legacy_switch_loop():
for switch_no in range(5):
# switch_no 0 is ALL, then 1=1, 2=2, 3=3, 4=4
# ON
print("switch %d ON" % switch_no)
radio.transmit(ON_MSGS[switch_no])
radio.send_payload(ON_MSGS[switch_no], REPEATS)
time.sleep(2)
 
# OFF
print("switch %d OFF" % switch_no)
radio.transmit(OFF_MSGS[switch_no])
radio.send_payload(OFF_MSGS[switch_no], REPEATS)
time.sleep(2)
def switch1_loop():
"""Repeatedly turn switch 1 ON then OFF"""
while True:
print("Switch 1 ON repeatedly")
while True:
radio.transmit(ON_MSGS[1])
print("Switch 1 ON")
radio.send_payload(ON_MSGS[1], REPEATS)
time.sleep(1)
 
#print("Switch 1 OFF")
#for i in range(50):
# radio.transmit(OFF_MSGS[1])
##time.sleep(1)
print("Switch 1 OFF")
radio.send_payload(OFF_MSGS[1], REPEATS)
time.sleep(1)
 
 
def pattern_test():
"""Test all patterns"""
p = raw_input("number 0..F")
p = int(p, 16)
msg = encoder.build_test_message(p)
print("pattern %s payload %s" % (str(hex(p)), encoder.ashex(msg)))
radio.transmit(msg)
radio.send_payload(msg, REPEATS)
 
if __name__ == "__main__":
 
print("starting legacy switch tester")
print("radio init")
radio.init()
print("radio as OOK")
radio.transmitter(ook=True)
radio.modulation(ook=True)
 
try:
#pattern_test()
#legacy_learn_mode()