Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add set_all in led client, updated exmpales #10

Merged
merged 6 commits into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions examples/blinky.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
from jacdac import Bus
from jacdac.led import LedClient
from jacdac import LoggerPriority
from time import sleep

if __name__ == '__main__':
def main():
bus = Bus()
led = LedClient(bus, "led")
speed = 0
brightness = 128
led.brightness = 0.5
# fade between colors
while True:
# blue
led.animate(0, 0, brightness, speed)
led.set_all(0xff0000)
sleep(1)
# off
led.animate(brightness, 0, 0, speed)
led.set_all(0x000000)
sleep(1)

main()
11 changes: 5 additions & 6 deletions examples/fade.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,17 @@
def main():
bus = Bus()
led = LedClient(bus, "led")
speed = 16
brightness = 128
# fade between colors
led.brightness = 0.5
# change between colors
while True:
# blue
led.animate(0, 0, brightness, speed)
led.set_all(0x0000ff)
sleep(1)
# red
led.animate(brightness, 0, 0, speed)
led.set_all(0xff0000)
sleep(1)
# green
led.animate(0, brightness, 0, speed)
led.set_all(0x00ff00)
sleep(1)

main()
11 changes: 3 additions & 8 deletions examples/slidy_blinky.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,12 @@ def main():
bus = Bus()
led = LedClient(bus, "led")
slider = PotentiometerClient(bus, "slider")
speed = 16
brightness = 128
led.set_all(0x0000ff)
# fade between colors
while True:
position = slider.position or 0.
brightness = int(position / 100. * 255.)
# blue
led.animate(0, 0, brightness, speed)
sleep(1)
# off
led.animate(brightness, 0, 0, speed)
# change brightness
led.brightness = position
sleep(1)

main()
6 changes: 3 additions & 3 deletions examples/weather_to_csv.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
from jacdac import Bus
from jacdac.humidity import HumidityClient
from jacdac.thermometer import ThermometerClient
from jacdac.temperature import TemperatureClient
import csv
from time import sleep

if __name__ == '__main__':
def main():
bus = Bus()
humidity_sensor = HumidityClient(bus, "weather.hum")
thermometer = ThermometerClient(bus, "weather.temp")
temperature = TemperatureClient(bus, "weather.temp")
with open('weather.csv', 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',', )
while True:
h = humidity_sensor.humidity
t = thermometer.temperature
t = temperature.temperature
writer.writerow([h, t])
sleep(1)
main()
2 changes: 0 additions & 2 deletions jacdac/base/__init__.py

This file was deleted.

6 changes: 0 additions & 6 deletions jacdac/base/constants.py

This file was deleted.

71 changes: 57 additions & 14 deletions jacdac/bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .role_manager.constants import *
from .unique_brain.constants import *
from .packet import *
from .transport import Transport

from .util import now, log, logv
from .pack import PackTuple, PackType, jdpack, jdunpack
Expand Down Expand Up @@ -179,18 +180,6 @@ def _service_matches(dev: 'Device', serv: bytearray):
return False
return True


class Transport:
"""A base class for packet transports"""

on_receive: Optional[Callable[[bytes], None]] = None
# Callback to report a received packet to the bus

def send(self, pkt: bytes) -> None:
# send a packet payload over the transport layer
pass


def rand_u64():
return bytearray([getrandbits(8) for _ in range(8)])

Expand Down Expand Up @@ -1690,7 +1679,7 @@ def packet_count(self):

@ property
def is_connected(self):
return self.clients != None
return len(self.clients) != 0

@ property
def short_id(self):
Expand Down Expand Up @@ -1735,7 +1724,7 @@ def _destroy(self):
self.debug("destroy")
for c in self.clients:
c._detach()
self.clients = None # type: ignore
self.clients = []

def _log_report_prefix(self) -> str:
return "{}>".format(self.short_id)
Expand Down Expand Up @@ -1784,3 +1773,57 @@ def process_packet(self, pkt: JDPacket):
# log(`handle pkt at ${client.role} rep=${pkt.serviceCommand}`)
c.device = self
c.handle_packet_outer(pkt)

class BufferClient(Client):
_value: bytearray
_dirty: bool

"""
A client that handles a double-buffer bytes buffer
"""
def __init__(self, bus: Bus, service_class: int, pack_formats: Dict[int, str], role: str) -> None:
super().__init__(bus, service_class, pack_formats, role)

self._value = bytearray(0)
self._dirty = False

@property
def value(self) -> bytearray:
"""
Cached reading value
"""
return self._value

@value.setter
def value(self, v: bytearray) -> None:
# TODO: check for equality
self._value = v or bytearray(0)
self._dirty = True
# TODO: debounce
self.refresh_value()

@property
def dirty(self) -> bool:
return self._dirty

def set_dirty(self) -> None:
self._dirty = True

def refresh_value(self) -> None:
if self._dirty:
print(self._value)
self.register(JD_REG_VALUE).set_values(self._value)
self._dirty = False

def update_value_length(self, length: Optional[int]) -> None:
l = len(self._value)
if (not length is None) and l != length:
# harmonize lengths
if length > l:
self._value = self._value + bytearray(length - l)
self._dirty = True
else:
self._value = self._value[0:length -1]
self._dirty = True


47 changes: 38 additions & 9 deletions jacdac/led/client.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Autogenerated file. Do not edit.
from jacdac.bus import Bus, Client
from jacdac.bus import Bus, BufferClient
from .constants import *
from typing import Optional


class LedClient(Client):
class LedClient(BufferClient):
"""
A controller for small displays of individually controlled RGB LEDs.
*
Expand All @@ -17,20 +17,21 @@ class LedClient(Client):
def __init__(self, bus: Bus, role: str) -> None:
super().__init__(bus, JD_SERVICE_CLASS_LED, JD_LED_PACK_FORMATS, role)


@property
def pixels(self) -> Optional[bytes]:
"""
A buffer of 24bit RGB color entries for each LED, in R, G, B order.
When writing, if the buffer is too short, the remaining pixels are set to `#000000`;
if the buffer is too long, the write may be ignored, or the additional pixels may be ignored.,
"""
return self.register(JD_LED_REG_PIXELS).value()
return self.value

@pixels.setter
def pixels(self, value: bytes) -> None:
self.register(JD_LED_REG_PIXELS).set_values(value)

if value is None:
self.value = bytearray(0)
else:
self.value = bytearray(value)

@property
def brightness(self) -> Optional[float]:
Expand All @@ -44,7 +45,6 @@ def brightness(self) -> Optional[float]:
def brightness(self, value: float) -> None:
self.register(JD_LED_REG_BRIGHTNESS).set_values(value / 100)


@property
def actual_brightness(self) -> Optional[float]:
"""
Expand Down Expand Up @@ -79,7 +79,6 @@ def max_power(self) -> Optional[int]:
def max_power(self, value: int) -> None:
self.register(JD_LED_REG_MAX_POWER).set_values(value)


@property
def leds_per_pixel(self) -> Optional[int]:
"""
Expand Down Expand Up @@ -110,4 +109,34 @@ def variant(self) -> Optional[LedVariant]:
"""
return self.register(JD_LED_REG_VARIANT).value()


def _sync(self):
self.register(JD_LED_REG_NUM_PIXELS).refresh()
n = self.num_pixels
if not n is None:
self.update_value_length(n * 3)

def show(self):
"""
Sends the buffer information to the server
"""
self._sync()
self.refresh_value()

def set_all(self, rgb: int):
"""
Sets all the colors to particular color
"""
self._sync()
r = (rgb >> 16) & 0xff
g = (rgb >> 8) & 0xff
b = (rgb >> 0) & 0xff
buf = self.value
dirty = self.dirty
for i in range(0, len(buf), 3):
dirty = dirty or buf[i] != r or buf[i + 1] != g or buf[i + 2] != b
buf[i] = r
buf[i + 1] = g
buf[i + 2] = b
if dirty:
self.set_dirty()
self.show()
2 changes: 0 additions & 2 deletions jacdac/sensor/__init__.py

This file was deleted.

6 changes: 0 additions & 6 deletions jacdac/sensor/constants.py

This file was deleted.

12 changes: 12 additions & 0 deletions jacdac/transport.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from typing import Callable, Optional


class Transport:
"""A base class for packet transports"""

on_receive: Optional[Callable[[bytes], None]] = None
# Callback to report a received packet to the bus

def send(self, pkt: bytes) -> None:
# send a packet payload over the transport layer
pass
2 changes: 1 addition & 1 deletion jacdac/transports/exec.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import threading
from jacdac.bus import Transport
from jacdac.transport import Transport
import subprocess

from jacdac.util import buf2hex, hex2buf
Expand Down
2 changes: 1 addition & 1 deletion jacdac/transports/hf2.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import struct
from typing import List

from jacdac.bus import Transport
from jacdac.transport import Transport

HF2_CMD_INFO = 0x0002
HF2_CMD_DMESG = 0x0010
Expand Down
2 changes: 1 addition & 1 deletion jacdac/transports/spi.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import List, Optional
from time import sleep
from tokenize import Number
from jacdac.bus import Transport
from jacdac.transport import Transport
from jacdac.util import buf2hex, hex2buf, now
from gpiod import Chip, Line, LineBulk, LINE_REQ_EV_RISING_EDGE, LINE_REQ_FLAG_ACTIVE_LOW, LINE_REQ_DIR_OUT # type: ignore
from spidev import SpiDev # type: ignore
Expand Down
2 changes: 1 addition & 1 deletion jacdac/transports/ws.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import threading
from typing import Optional
import websocket # type: ignore
from jacdac.bus import Transport
from jacdac.transport import Transport


class WebSocketTransport(Transport):
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
setup(
version=JD_VERSION,
packages=find_packages(
include=['jacdac', 'jacdac.*'], exclude=['*test.py', 'jacdac.examples.*'])
include=['jacdac', 'jacdac.*'], exclude=['*test.py'])

)