From 3fa3a67424e95089a5fdacf93eb1b53536786779 Mon Sep 17 00:00:00 2001 From: embeddeddev88 Date: Thu, 22 Dec 2022 11:32:03 +0000 Subject: [PATCH 1/7] Initial --- .../__pycache__/espresso_pb2.cpython-37.pyc | Bin 0 -> 1933 bytes .../espresso_pb2_grpc.cpython-37.pyc | Bin 0 -> 4133 bytes pkg/espressopb/espresso_pb2.py | 38 +++++ pkg/espressopb/espresso_pb2_grpc.py | 132 ++++++++++++++++++ pkg/espressopb/grpc_client_micro_oled.py | 93 ++++++++++++ 5 files changed, 263 insertions(+) create mode 100644 pkg/espressopb/__pycache__/espresso_pb2.cpython-37.pyc create mode 100644 pkg/espressopb/__pycache__/espresso_pb2_grpc.cpython-37.pyc create mode 100644 pkg/espressopb/espresso_pb2.py create mode 100644 pkg/espressopb/espresso_pb2_grpc.py create mode 100644 pkg/espressopb/grpc_client_micro_oled.py diff --git a/pkg/espressopb/__pycache__/espresso_pb2.cpython-37.pyc b/pkg/espressopb/__pycache__/espresso_pb2.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0308b09361828f821126d14b1a221c97616266c3 GIT binary patch literal 1933 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 literal 0 HcmV?d00001 diff --git a/pkg/espressopb/espresso_pb2.py b/pkg/espressopb/espresso_pb2.py new file mode 100644 index 0000000..fb24d67 --- /dev/null +++ b/pkg/espressopb/espresso_pb2.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: espresso.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x65spresso.proto\x12\nespressopb\x1a\x1fgoogle/protobuf/timestamp.proto\"S\n\x11TemperatureSample\x12\r\n\x05value\x18\x01 \x01(\x02\x12/\n\x0bobserved_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"D\n\x12TemperatureHistory\x12.\n\x07samples\x18\x01 \x03(\x0b\x32\x1d.espressopb.TemperatureSample\"\x1a\n\x18TemperatureStreamRequest\"\x87\x01\n\x19TemperatureStreamResponse\x12\x31\n\x07history\x18\x01 \x01(\x0b\x32\x1e.espressopb.TemperatureHistoryH\x00\x12/\n\x06sample\x18\x02 \x01(\x0b\x32\x1d.espressopb.TemperatureSampleH\x00\x42\x06\n\x04\x64\x61ta\"\x19\n\x17GetConfigurationRequest\"q\n\rConfiguration\x12\x13\n\x0btemperature\x18\x01 \x01(\x02\x12\t\n\x01p\x18\x02 \x01(\x02\x12\t\n\x01i\x18\x03 \x01(\x02\x12\t\n\x01\x64\x18\x04 \x01(\x02\x12*\n\x06set_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp2\x8c\x02\n\x08\x45spresso\x12\x62\n\x11\x42oilerTemperature\x12$.espressopb.TemperatureStreamRequest\x1a%.espressopb.TemperatureStreamResponse0\x01\x12R\n\x10GetConfiguration\x12#.espressopb.GetConfigurationRequest\x1a\x19.espressopb.Configuration\x12H\n\x10SetConfiguration\x12\x19.espressopb.Configuration\x1a\x19.espressopb.Configurationb\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'espresso_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _TEMPERATURESAMPLE._serialized_start=63 + _TEMPERATURESAMPLE._serialized_end=146 + _TEMPERATUREHISTORY._serialized_start=148 + _TEMPERATUREHISTORY._serialized_end=216 + _TEMPERATURESTREAMREQUEST._serialized_start=218 + _TEMPERATURESTREAMREQUEST._serialized_end=244 + _TEMPERATURESTREAMRESPONSE._serialized_start=247 + _TEMPERATURESTREAMRESPONSE._serialized_end=382 + _GETCONFIGURATIONREQUEST._serialized_start=384 + _GETCONFIGURATIONREQUEST._serialized_end=409 + _CONFIGURATION._serialized_start=411 + _CONFIGURATION._serialized_end=524 + _ESPRESSO._serialized_start=527 + _ESPRESSO._serialized_end=795 +# @@protoc_insertion_point(module_scope) diff --git a/pkg/espressopb/espresso_pb2_grpc.py b/pkg/espressopb/espresso_pb2_grpc.py new file mode 100644 index 0000000..edf1a2a --- /dev/null +++ b/pkg/espressopb/espresso_pb2_grpc.py @@ -0,0 +1,132 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +import espresso_pb2 as espresso__pb2 + + +class EspressoStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.BoilerTemperature = channel.unary_stream( + '/espressopb.Espresso/BoilerTemperature', + request_serializer=espresso__pb2.TemperatureStreamRequest.SerializeToString, + response_deserializer=espresso__pb2.TemperatureStreamResponse.FromString, + ) + self.GetConfiguration = channel.unary_unary( + '/espressopb.Espresso/GetConfiguration', + request_serializer=espresso__pb2.GetConfigurationRequest.SerializeToString, + response_deserializer=espresso__pb2.Configuration.FromString, + ) + self.SetConfiguration = channel.unary_unary( + '/espressopb.Espresso/SetConfiguration', + request_serializer=espresso__pb2.Configuration.SerializeToString, + response_deserializer=espresso__pb2.Configuration.FromString, + ) + + +class EspressoServicer(object): + """Missing associated documentation comment in .proto file.""" + + def BoilerTemperature(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetConfiguration(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def SetConfiguration(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_EspressoServicer_to_server(servicer, server): + rpc_method_handlers = { + 'BoilerTemperature': grpc.unary_stream_rpc_method_handler( + servicer.BoilerTemperature, + request_deserializer=espresso__pb2.TemperatureStreamRequest.FromString, + response_serializer=espresso__pb2.TemperatureStreamResponse.SerializeToString, + ), + 'GetConfiguration': grpc.unary_unary_rpc_method_handler( + servicer.GetConfiguration, + request_deserializer=espresso__pb2.GetConfigurationRequest.FromString, + response_serializer=espresso__pb2.Configuration.SerializeToString, + ), + 'SetConfiguration': grpc.unary_unary_rpc_method_handler( + servicer.SetConfiguration, + request_deserializer=espresso__pb2.Configuration.FromString, + response_serializer=espresso__pb2.Configuration.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'espressopb.Espresso', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class Espresso(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def BoilerTemperature(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream(request, target, '/espressopb.Espresso/BoilerTemperature', + espresso__pb2.TemperatureStreamRequest.SerializeToString, + espresso__pb2.TemperatureStreamResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def GetConfiguration(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/espressopb.Espresso/GetConfiguration', + espresso__pb2.GetConfigurationRequest.SerializeToString, + espresso__pb2.Configuration.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def SetConfiguration(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/espressopb.Espresso/SetConfiguration', + espresso__pb2.Configuration.SerializeToString, + espresso__pb2.Configuration.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/pkg/espressopb/grpc_client_micro_oled.py b/pkg/espressopb/grpc_client_micro_oled.py new file mode 100644 index 0000000..1a2cfbc --- /dev/null +++ b/pkg/espressopb/grpc_client_micro_oled.py @@ -0,0 +1,93 @@ +""" +This demo will fill the screen with white, draw a black box on top +and then print Hello World! in the center of the display + +This example is for use on (Linux) computers that are using CPython with +Adafruit Blinka to support CircuitPython libraries. CircuitPython does +not support PIL/pillow (python imaging library)! + +We are using Sparkfun micro OLED breakout (Qwiic), article LCD-14532 +""" + +import board +import digitalio +from PIL import Image, ImageDraw, ImageFont +import adafruit_ssd1306 +import grpc +import espresso_pb2 +import espresso_pb2_grpc +import requests +import os +import subprocess +import sys, time + +# Define the Reset Pin +oled_reset = digitalio.DigitalInOut(board.D4) + +# Change these +# to the right size for your display! +WIDTH = 64 +HEIGHT = 48 # Change to 64 if needed +BORDER = 0 + +# Use for I2C. +i2c = board.I2C() +oled = adafruit_ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c, addr=0x3D, reset=oled_reset) + +# Use for SPI +# spi = board.SPI() +# oled_cs = digitalio.DigitalInOut(board.D5) +# oled_dc = digitalio.DigitalInOut(board.D6) +# oled = adafruit_ssd1306.SSD1306_SPI(WIDTH, HEIGHT, spi, oled_dc, oled_reset, oled_cs) + +# Clear display. +oled.fill(0) +oled.show() + +# Create blank image for drawing. +# Make sure to create image with mode '1' for 1-bit color. +image = Image.new("1", (oled.width, oled.height)) + +# Get drawing object to draw on image. +draw = ImageDraw.Draw(image) + +# Draw a white background +draw.rectangle((0, 0, oled.width, oled.height), outline=255, fill=255) + +# Draw a smaller inner rectangle +draw.rectangle( + (BORDER, BORDER, oled.width - BORDER - 1, oled.height - BORDER - 1), + outline=0, + fill=0, +) +# Load default font. +#font = ImageFont.load_default() +font = ImageFont.truetype("DejaVuSans-Oblique.ttf", size=15) + +def print_to_oled( temperature ): + # Create blank image for drawing. + # Make sure to create image with mode '1' for 1-bit color. + image = Image.new("1", (oled.width, oled.height)) + # Get drawing object to draw on image. + draw = ImageDraw.Draw(image) + # Clear display. + oled.fill(0) + text = str(temperature)+"°C" + (font_width, font_height) = font.getsize(str(text)) + draw.text( + (oled.width // 2 - font_width // 2, oled.height // 2 - font_height // 2), + text, + font=font, + fill=255, + ) + oled.image(image) + oled.show() + +def run(): + with grpc.insecure_channel('localhost:8080') as channel: + stub = espresso_pb2_grpc.EspressoStub(channel) + response_iterator = stub.BoilerTemperature(espresso_pb2.TemperatureStreamRequest()) + for response in response_iterator: + print(response.sample.value) + print_to_oled(float(f'{response.sample.value:.1f}')) +run() \ No newline at end of file From 84e26d3293b3f3efdb7fa3798e61b3084b46ee53 Mon Sep 17 00:00:00 2001 From: embeddeddev88 Date: Thu, 22 Dec 2022 11:45:15 +0000 Subject: [PATCH 2/7] Added systemd folder --- .../__pycache__/espresso_pb2.cpython-37.pyc | Bin 1933 -> 1933 bytes .../espresso_pb2_grpc.cpython-37.pyc | Bin 4133 -> 4133 bytes systemd/espresso.service | 11 +++++++++++ systemd/micro_oled.service | 11 +++++++++++ systemd/readme.md | 6 ++++++ 5 files changed, 28 insertions(+) create mode 100644 systemd/espresso.service create mode 100644 systemd/micro_oled.service create mode 100644 systemd/readme.md diff --git a/pkg/espressopb/__pycache__/espresso_pb2.cpython-37.pyc b/pkg/espressopb/__pycache__/espresso_pb2.cpython-37.pyc index 0308b09361828f821126d14b1a221c97616266c3..ef990a221e2952313e1c6abb05d86849a863c75a 100644 GIT binary patch delta 20 ZcmeC>@8#!q;^pOH00LEqB^$Y$*a0Uh1NZ;{ delta 20 acmeC>@8#!q;^pOH0D@Jw7jEQkVg~>&U Date: Thu, 22 Dec 2022 12:23:50 +0000 Subject: [PATCH 3/7] espresso service should run with pi user --- systemd/espresso.service | 1 + 1 file changed, 1 insertion(+) diff --git a/systemd/espresso.service b/systemd/espresso.service index 40b825f..79beab8 100644 --- a/systemd/espresso.service +++ b/systemd/espresso.service @@ -5,6 +5,7 @@ After=multi-user.target [Service] #Environment="SCRIPT_ARGS=--boiler-therm-clk-pin 23 --boiler-therm-cs-pin 27 --boiler-therm-miso-pin 22 --verbose" #Environment ="SCRIPT_ARGS=%I" +User=pi ExecStart=/bin/bash --login -c "/usr/bin/espresso --boiler-therm-clk-pin 23 --boiler-therm-cs-pin 27 --boiler-therm-miso-pin 22 --verbose" [Install] WantedBy=multi-user.target From daedeef5f039527bea3d753556d88caaf7919dae Mon Sep 17 00:00:00 2001 From: embeddeddev88 Date: Sat, 31 Dec 2022 10:03:27 +0000 Subject: [PATCH 4/7] restarting service on failure every 5sec --- systemd/espresso.service | 4 ++-- systemd/micro_oled.service | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/systemd/espresso.service b/systemd/espresso.service index 79beab8..34d958f 100644 --- a/systemd/espresso.service +++ b/systemd/espresso.service @@ -3,8 +3,8 @@ Description=Espresso PID service After=multi-user.target [Service] -#Environment="SCRIPT_ARGS=--boiler-therm-clk-pin 23 --boiler-therm-cs-pin 27 --boiler-therm-miso-pin 22 --verbose" -#Environment ="SCRIPT_ARGS=%I" +Restart=on-failure +RestartSec=5s User=pi ExecStart=/bin/bash --login -c "/usr/bin/espresso --boiler-therm-clk-pin 23 --boiler-therm-cs-pin 27 --boiler-therm-miso-pin 22 --verbose" [Install] diff --git a/systemd/micro_oled.service b/systemd/micro_oled.service index a58a13d..311cff1 100644 --- a/systemd/micro_oled.service +++ b/systemd/micro_oled.service @@ -3,6 +3,8 @@ Description=Sparkfun micro oled service After=multi-user.target espresso.service [Service] +Restart=on-failure +RestartSec=5s User=pi ExecStart=/usr/bin/python3 /home/pi/espresso-controller/pkg/espressopb/grpc_client_micro_oled.py From 25f2a38e20be8e041d64e174fa9f9215671fd54d Mon Sep 17 00:00:00 2001 From: embeddeddev88 Date: Sat, 31 Dec 2022 14:51:55 +0000 Subject: [PATCH 5/7] moved grpc clients into own dir --- .../__pycache__/espresso_pb2.cpython-37.pyc | Bin 1933 -> 0 bytes .../__pycache__/espresso_pb2_grpc.cpython-37.pyc | Bin 4133 -> 0 bytes pkg/{espressopb => oled}/espresso_pb2.py | 0 pkg/{espressopb => oled}/espresso_pb2_grpc.py | 0 .../grpc_client_micro_oled.py | 0 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pkg/espressopb/__pycache__/espresso_pb2.cpython-37.pyc delete mode 100644 pkg/espressopb/__pycache__/espresso_pb2_grpc.cpython-37.pyc rename pkg/{espressopb => oled}/espresso_pb2.py (100%) rename pkg/{espressopb => oled}/espresso_pb2_grpc.py (100%) rename pkg/{espressopb => oled}/grpc_client_micro_oled.py (100%) diff --git a/pkg/espressopb/__pycache__/espresso_pb2.cpython-37.pyc b/pkg/espressopb/__pycache__/espresso_pb2.cpython-37.pyc deleted file mode 100644 index ef990a221e2952313e1c6abb05d86849a863c75a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1933 zcmah}&2QsG6t|r;Nhja#?$*h&ZPjHFMIwQ41i|*h{g7x=;`G2=Mt0^kYu3qlZD*zK z0U>eV!U=IfTv~|>|IsSq#;JECBu>0>lE#g;ySDt(Z{ECl^XBJyZ>Lx!3O-Ms{?P+u zf6Kw_Swiv@zwj>vu26-mT=Ud{MpLTfDK9-(qM4Ydk!NWx=1a(zDNz+5m-#D&7SK0? zwjwQ|EhlZ4WuCoKX$4Z3Rj7deqjII;T&SjMW`V!AsW04b>tO9gID1pavjm&EASrjdx!?V508*PKs5L&tRXiL4Nfd&tM+RB z0EQ6Q5%3K^5RvE!Z^Id#pF^UX=pC6beg@BL@v!tA2Ss@Xre{tAon`WFemN_Z_{Ea4vs|01~Gs|Y_x_)Ws^ z5(*kZS;9jsyshs^j2t&P0OB^7aRi&q|iK@SAUR}mP*1B z_k%!oQ#3F11e)E0b9>}PG%KeVcY=&`{9v*VrWdhU@yCOk2Ee2iw7Si?1%YdO?knK? zcv~phGp*gu(P_8cp=&#`T^(b0vHP$+HB3M9WDN3^`p%t~)%k zFy(J)Eorp69drA*V}5gHT3uRy)0B1EKCw({umiKZ+dkPpIyl2bj@l=)RV8-IOqZEy zonoF=`%fjPqS`V1_j&V~7+|Y)o3q>YaZe1RKzLY!P5*iS#_l^eRQ`m9e=*K|F%W#@ e!I$#yhb@G(T9~}4T&j>NX(hFy5-p?N{r(RSCsX|Z diff --git a/pkg/espressopb/__pycache__/espresso_pb2_grpc.cpython-37.pyc b/pkg/espressopb/__pycache__/espresso_pb2_grpc.cpython-37.pyc deleted file mode 100644 index b8af604c463791d371703558f016e9a0c9cac5d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4133 zcmds4TW=Fb6yBTH>sv4lmq1%Es8qFDoR(gMP*nxefRGvs5&Ghn)n;cB*0p!d%(?|@ zc`3Z|5Bd6UKe&nJR4gx8;Y=wysT#k~MMe%+sOmWiBMnQ^OSQ3thkTFQ3B!*N&nzW+0)zJdA_M!prgmfP@`j*f)(dAu` z%6<2V*W%ABu{CK{Vk)oy=7vxzG3u_Td^W1I;vU$Skdu&vv! ztNJ(LVX=D|=kW+MCkX!nX*Taa@{@3@;ws*dl>M7;+E3usoIS+bd|OmbDdDU#uI z+wmg^s9G+Ars{O@F|#Whhn}dK#eJ$-d>^27Bp>Xl@>E;D8DbTd^XJC;{bb13N6{S3 z%V83yA{jt8>!Tm`=ls#`d`O7+TGyjT%Jcmwj#A&RkvWnp7_MVlrfaTPhrg4PGu@LT zbY{Qn!bNaM91OYdtE%r06E+^uxbFK8#=&5^QuclLiSLV(xI#<6Ku!>k9K%DG6jD6X zu{3A7&whk0%YBxW;JXMgtcG>f8obAuBJv`>YM2D1CY!*Fmf+` zZkjZ6m`S6w#LOq=&j^c<#eVafC#Sc0dOu;UI6-t7js~3K3}+X*ZC81cr+%0)t{hUW zs_q~hjpZhB8sB$sZ{PWDYkRAEZ|hrCqpggmK{SwRwVR~3U!1iiL?YU@IF9$I^3n5qY1;IU?tYv_PhqhzrEH zNQ4|PC)#?CVfr!pA{G~pU{Un-|0NVn!0_2Cp(qBqZo4c{To~ds5sF0O3=uLiLFfuP zcL8>-0FC`wERaqlg%64xp6j`Sxbv(_F{O;Iy|s@)YV^&_=v%2x85h(=t~H<8;CtX# zz^Q6}?GV2Xer=J@tY7TMR%#qHn4MYAt;cp|9;{^cp7woaz~`MV0{DqpZd^=*YIU9+ zU*txZ+Tk}(R{7Bc+&-plRh?hVdp=y>AL=OKBabs=f&46TP(kk(RLO}75duq{TS!^U zeyxFT(DoG~qylyR@D0-6=P|NqIJ;7<1&qy^B+^tC*>-veRCx$iE{(Y8tsWIxs$+#S z7xYdlSLf)8qI>yiLZt@|y^1}OJlH@MbCAudg>Tb#OwSbLu_0}nH9}?sU0wrO%rM+x zsI5@AB9`|`nALURN;4F)tf7lnnxSHY&R3K-lkUwUzJ7G~W~i%g$U|RJh&JL+Fd!p7 zurid8C?FRMIkPf5D`igRX64MwD$g4b$?Cp#Dd*+3Rp$>;-9@^#9SAB~#S23s^T`c~ z#A;V{XjE<*h<%=_ax$U<4hd#jviPCk4EYLmp;XN<7z_?^ya@GGh%!>uP(bT)6F*lg zKLsdG_7dTvtYeQ^m@O{0i zww=Q(E)#-vA{tfgWg1oOY73}}4sBW|@+lDtuHp)j&xw3N z*-O>MC0&OC1gMPnSuiysz`p{u?UPCD|=PsO8zsv&~c9+F$e-BMJZj diff --git a/pkg/espressopb/espresso_pb2.py b/pkg/oled/espresso_pb2.py similarity index 100% rename from pkg/espressopb/espresso_pb2.py rename to pkg/oled/espresso_pb2.py diff --git a/pkg/espressopb/espresso_pb2_grpc.py b/pkg/oled/espresso_pb2_grpc.py similarity index 100% rename from pkg/espressopb/espresso_pb2_grpc.py rename to pkg/oled/espresso_pb2_grpc.py diff --git a/pkg/espressopb/grpc_client_micro_oled.py b/pkg/oled/grpc_client_micro_oled.py similarity index 100% rename from pkg/espressopb/grpc_client_micro_oled.py rename to pkg/oled/grpc_client_micro_oled.py From f95ec09b2def4a8433a33aad3b796663a56f1795 Mon Sep 17 00:00:00 2001 From: embeddeddev88 Date: Sat, 7 Jan 2023 13:15:12 +0000 Subject: [PATCH 6/7] changing to from adafruit library to sparkfun and other refactoring details --- pkg/oled/grpc_client_micro_oled.py | 83 +++++++----------------------- 1 file changed, 19 insertions(+), 64 deletions(-) diff --git a/pkg/oled/grpc_client_micro_oled.py b/pkg/oled/grpc_client_micro_oled.py index 1a2cfbc..3a4a540 100644 --- a/pkg/oled/grpc_client_micro_oled.py +++ b/pkg/oled/grpc_client_micro_oled.py @@ -1,18 +1,19 @@ +#!/usr/bin/env python3 """ -This demo will fill the screen with white, draw a black box on top -and then print Hello World! in the center of the display +We are using Sparkfun micro OLED breakout (Qwiic), article LCD-14532 -This example is for use on (Linux) computers that are using CPython with -Adafruit Blinka to support CircuitPython libraries. CircuitPython does -not support PIL/pillow (python imaging library)! +Prereqs: +* install DSEG font: sudo apt-get install fonts-dseg +* all packages need to be installed including luma -We are using Sparkfun micro OLED breakout (Qwiic), article LCD-14532 """ import board import digitalio from PIL import Image, ImageDraw, ImageFont -import adafruit_ssd1306 +from luma.core.interface.serial import i2c +from luma.core.render import canvas +from luma.oled.device import ssd1306 import grpc import espresso_pb2 import espresso_pb2_grpc @@ -21,67 +22,21 @@ import subprocess import sys, time -# Define the Reset Pin -oled_reset = digitalio.DigitalInOut(board.D4) - -# Change these -# to the right size for your display! -WIDTH = 64 -HEIGHT = 48 # Change to 64 if needed -BORDER = 0 - # Use for I2C. -i2c = board.I2C() -oled = adafruit_ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c, addr=0x3D, reset=oled_reset) - -# Use for SPI -# spi = board.SPI() -# oled_cs = digitalio.DigitalInOut(board.D5) -# oled_dc = digitalio.DigitalInOut(board.D6) -# oled = adafruit_ssd1306.SSD1306_SPI(WIDTH, HEIGHT, spi, oled_dc, oled_reset, oled_cs) - -# Clear display. -oled.fill(0) -oled.show() - -# Create blank image for drawing. -# Make sure to create image with mode '1' for 1-bit color. -image = Image.new("1", (oled.width, oled.height)) - -# Get drawing object to draw on image. -draw = ImageDraw.Draw(image) - -# Draw a white background -draw.rectangle((0, 0, oled.width, oled.height), outline=255, fill=255) - -# Draw a smaller inner rectangle -draw.rectangle( - (BORDER, BORDER, oled.width - BORDER - 1, oled.height - BORDER - 1), - outline=0, - fill=0, -) -# Load default font. -#font = ImageFont.load_default() -font = ImageFont.truetype("DejaVuSans-Oblique.ttf", size=15) +serial = i2c(port=1, address=0x3D) +device = ssd1306(serial, width=64, height=48, rotate=2) +font = ImageFont.truetype("LiberationSerif-Bold.ttf", size=15) def print_to_oled( temperature ): - # Create blank image for drawing. - # Make sure to create image with mode '1' for 1-bit color. - image = Image.new("1", (oled.width, oled.height)) - # Get drawing object to draw on image. - draw = ImageDraw.Draw(image) - # Clear display. - oled.fill(0) text = str(temperature)+"°C" (font_width, font_height) = font.getsize(str(text)) - draw.text( - (oled.width // 2 - font_width // 2, oled.height // 2 - font_height // 2), - text, - font=font, - fill=255, - ) - oled.image(image) - oled.show() + with canvas(device) as draw: + draw.rectangle(device.bounding_box, outline="white", fill="black") + draw.text((device.width // 2 - font_width // 2, device.height // 2 - font_height // 2), + text, + font=font, + fill="white", + ) def run(): with grpc.insecure_channel('localhost:8080') as channel: @@ -90,4 +45,4 @@ def run(): for response in response_iterator: print(response.sample.value) print_to_oled(float(f'{response.sample.value:.1f}')) -run() \ No newline at end of file +run() From 19d847806cb1a3fa8edbc15de25d14d883b8d55e Mon Sep 17 00:00:00 2001 From: embeddeddev88 Date: Sat, 7 Jan 2023 22:24:41 +0000 Subject: [PATCH 7/7] added date and time string on top and error stream on the bottom --- pkg/oled/grpc_client_micro_oled.py | 47 +++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/pkg/oled/grpc_client_micro_oled.py b/pkg/oled/grpc_client_micro_oled.py index 3a4a540..dbc7b54 100644 --- a/pkg/oled/grpc_client_micro_oled.py +++ b/pkg/oled/grpc_client_micro_oled.py @@ -3,11 +3,10 @@ We are using Sparkfun micro OLED breakout (Qwiic), article LCD-14532 Prereqs: -* install DSEG font: sudo apt-get install fonts-dseg * all packages need to be installed including luma - +* I2C is enabled on port 1 """ - +import datetime import board import digitalio from PIL import Image, ImageDraw, ImageFont @@ -26,23 +25,45 @@ serial = i2c(port=1, address=0x3D) device = ssd1306(serial, width=64, height=48, rotate=2) font = ImageFont.truetype("LiberationSerif-Bold.ttf", size=15) +aux_font = ImageFont.truetype("LiberationSerif-Bold.ttf", size=10) -def print_to_oled( temperature ): - text = str(temperature)+"°C" - (font_width, font_height) = font.getsize(str(text)) +def print_to_oled( temp,error ): + t_now = datetime.datetime.now(datetime.timezone.utc).strftime("%d-%m/%H:%M:%S") + (tfont_width, tfont_height) = font.getsize(t_now) + (font_width, font_height) = font.getsize(str(temp)) + error_str = "Delta T="+str(error)+"°C" + (error_font_width, error_font_height) = font.getsize(error_str) with canvas(device) as draw: draw.rectangle(device.bounding_box, outline="white", fill="black") - draw.text((device.width // 2 - font_width // 2, device.height // 2 - font_height // 2), - text, - font=font, - fill="white", + draw.text((device.width // 2 - font_width // 2, + device.height // 2 - font_height // 2), + temp, + font=font, + fill="white", ) + draw.text((device.width // 2 - tfont_width // 3.1, + device.height // 10 - tfont_height // 10), + t_now, + font=aux_font, + fill="green", + ) + draw.text((device.width // 2 - error_font_width // 3.1, + device.height // 2 - error_font_height // -1.4), + error_str, + font=aux_font, + fill="white",) def run(): with grpc.insecure_channel('localhost:8080') as channel: stub = espresso_pb2_grpc.EspressoStub(channel) - response_iterator = stub.BoilerTemperature(espresso_pb2.TemperatureStreamRequest()) - for response in response_iterator: + #TODO: Initialize the PID values once here to P=1, I=4, D=8 + + response_iter_temp = stub.BoilerTemperature(espresso_pb2.TemperatureStreamRequest()) + for response in response_iter_temp: print(response.sample.value) - print_to_oled(float(f'{response.sample.value:.1f}')) + response_setT = stub.GetConfiguration(espresso_pb2.GetConfigurationRequest()) + print(str(response_setT.temperature)) + error = response_setT.temperature - response.sample.value + print_to_oled(str(float(f'{response.sample.value:.1f}'))+"°C",error) + #TODO: display an image of steaming cup if error is < 5°C run()