Skip to content

Commit

Permalink
Chuangmi IR: Add ability to send any Pronto Hex encoded IR command (#183
Browse files Browse the repository at this point in the history
)
  • Loading branch information
yawor authored and syssi committed Jan 27, 2018
1 parent 18d422f commit 2eaa154
Showing 1 changed file with 78 additions and 0 deletions.
78 changes: 78 additions & 0 deletions miio/chuangmi_ir.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import base64
from construct import (
Struct, Const, Rebuild, this, len_, Adapter, Computed,
Int16ul, Int32ul, Int16ub, Array, BitStruct, BitsInteger,
)
from .device import Device, DeviceException


Expand Down Expand Up @@ -34,3 +39,76 @@ def play(self, command: str, frequency: int):
frequency = 38400
return self.send("miIO.ir_play",
{'freq': frequency, 'code': command})

def play_pronto(self, pronto: str, repeats: int=0):
"""Play a Pronto Hex encoded IR command.
Supports only raw Pronto format, starting with 0000.
:param str pronto: Pronto Hex string.
:param int repeats: Number of extra signal repeats."""
if repeats < 0:
raise ChuangmiIrException('Invalid repeats value')

try:
pronto_data = Pronto.parse(bytearray.fromhex(pronto))
except Exception as ex:
raise ChuangmiIrException from ex

if len(pronto_data.intro) == 0:
repeats += 1

times = set()
for pair in pronto_data.intro + pronto_data.repeat * (1 if repeats else 0):
times.add(pair.pulse)
times.add(pair.gap)

times = sorted(times)
times_map = {t: idx for idx, t in enumerate(times)}
edge_pairs = []
for pair in pronto_data.intro + pronto_data.repeat * repeats:
edge_pairs.append({
'pulse': times_map[pair.pulse],
'gap': times_map[pair.gap],
})

signal_code = base64.b64encode(ChuangmiIrSignal.build({
'times_index': times + [0] * (16 - len(times)),
'edge_pairs': edge_pairs,
})).decode()

return self.play(signal_code, int(round(pronto_data.frequency)))


class ProntoPulseAdapter(Adapter):
def _decode(self, obj, context):
return int(obj * context._.modulation_period)

def _encode(self, obj, context):
raise RuntimeError('Not implemented')


ChuangmiIrSignal = Struct(
Const(0xa567, Int16ul),
'edge_count' / Rebuild(Int16ul, len_(this.edge_pairs) * 2 - 1),
'times_index' / Array(16, Int32ul),
'edge_pairs' / Array((this.edge_count + 1) / 2, BitStruct(
'gap' / BitsInteger(4),
'pulse' / BitsInteger(4),
))
)

ProntoBurstPair = Struct(
'pulse' / ProntoPulseAdapter(Int16ub),
'gap' / ProntoPulseAdapter(Int16ub),
)

Pronto = Struct(
Const(0, Int16ub),
'_ticks' / Int16ub,
'modulation_period' / Computed(this._ticks * 0.241246),
'frequency' / Computed(1000000 / this.modulation_period),
'intro_len' / Int16ub,
'repeat_len' / Int16ub,
'intro' / Array(this.intro_len, ProntoBurstPair),
'repeat' / Array(this.repeat_len, ProntoBurstPair),
)

0 comments on commit 2eaa154

Please sign in to comment.