From 15071bbcaa844763ce6793e3471e87ff15056a3f Mon Sep 17 00:00:00 2001 From: dWiGhT Date: Wed, 3 Nov 2021 12:09:22 -0700 Subject: [PATCH 1/4] improvement: colorize the menu items for better visibility --- .gitignore | 7 ++++++- airq/__main__.py | 7 ++++++- airq/app.py | 33 +++++++++++++++++++++++++++++++-- airq/consts.py | 24 ++++++++++++------------ requirements.txt | 8 ++++++++ setup.py | 6 +++--- 6 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index cadfde9..c2f265d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,9 @@ session __pycache__ .DS_Store build -dist \ No newline at end of file +dist + +.eggs/ +.idea/ +AirQ.egg-info/ + diff --git a/airq/__main__.py b/airq/__main__.py index 19865ff..d8ed681 100644 --- a/airq/__main__.py +++ b/airq/__main__.py @@ -1,16 +1,21 @@ -__version__ = "0.1.0" +__version__ = "0.2.0" import os +import logging from dotenv import load_dotenv from airq.app import App from airq.api import Uhoo +logger = logging.getLogger(__name__) + load_dotenv() USERNAME = os.getenv("USERNAME") PASSWORD = os.getenv("PASSWORD") if __name__ == "__main__": + logger.info("Starting AirQ v%s", __version__) app = App(Uhoo(USERNAME, PASSWORD)) app.run() + logger.info("Exiting AirQ v%s", __version__) diff --git a/airq/app.py b/airq/app.py index 7c5015b..3ee31d3 100644 --- a/airq/app.py +++ b/airq/app.py @@ -1,8 +1,13 @@ import json from datetime import datetime import rumps -from airq import consts +from AppKit import NSAttributedString +from PyObjCTools.Conversion import propertyListFromPythonCollection +from Cocoa import (NSFont, NSFontAttributeName, + NSColor, NSForegroundColorAttributeName) + +from airq import consts class App(rumps.App): def __init__(self, api): @@ -53,17 +58,41 @@ def update_icon(self, data): def update_values(self, data): values = data[0] for key, label in consts.LABELS.items(): + warningColor = None if key == consts.KEY_LASTFETCH: value = datetime.now() elif key == consts.KEY_TIMESTAMP: value = datetime.fromtimestamp(values[key]) elif not isinstance(values[key], int): value = values[key]["value"] + warningColor = values[key]["color"] else: value = values[key] - new_title = label.format(value) + (" ⚠️" if key in self.warns else "") + + if key == consts.KEY_TEMP: + new_title = label.format(value, (value - 32) / 1.8) + else: + new_title = label.format(value) self.menu[key].title = new_title + # if key in self.warns: + if warningColor == 'yellow': + color = NSColor.colorWithCalibratedRed_green_blue_alpha_(204/255, 204/255, 0, 1) + font = NSFont.fontWithName_size_("Courier-Bold", 14.0) + elif warningColor == 'red': + color = NSColor.colorWithCalibratedRed_green_blue_alpha_(1, 0, 0, 1) + font = NSFont.fontWithName_size_("Courier-Bold", 14.0) + else: + color = NSColor.colorWithCalibratedRed_green_blue_alpha_(0, 186.0/255, 44.0/255, 1) + font = NSFont.fontWithName_size_("Courier", 14.0) + + attributes = propertyListFromPythonCollection({ + NSFontAttributeName: font, + NSForegroundColorAttributeName: color} + , conversionHelper=lambda x: x) + string = NSAttributedString.alloc().initWithString_attributes_(new_title, attributes) + self.menu[key]._menuitem.setAttributedTitle_(string) + @rumps.clicked("Debug") def debug(self, sender): rumps.Window( diff --git a/airq/consts.py b/airq/consts.py index 20174f7..859ae28 100644 --- a/airq/consts.py +++ b/airq/consts.py @@ -12,18 +12,18 @@ KEY_LASTFETCH = "lastfetch" LABELS = { - KEY_CO: "CO {} ppm", - KEY_CO2: "CO₂ {} ppm", - KEY_NO2: "NO₂ {} ppb", - KEY_VOC: "TVOC {} ppb", - KEY_DUST: "Dust {} ug/m³", - KEY_TEMP: "Temp {} °C", - KEY_OZONE: "Ozone {} ppb", - KEY_PRESSURE: "Pressure {} hPa", - KEY_HUMIDITY: "Humidity {} %", - KEY_VIRUSSCORE: "Virus Score {}/10", - KEY_TIMESTAMP: "Measured {:%H:%M:%S}", - KEY_LASTFETCH: "Retrieved {:%H:%M:%S}", + KEY_CO: " CO: {} ppm", + KEY_CO2: " CO₂: {} ppm", + KEY_NO2: " NO₂: {} ppb", + KEY_VOC: " TVOC: {} ppb", + KEY_DUST: " Dust: {} ug/m³", + KEY_TEMP: " Temp: {:.1f}°F/{:.1f}°C", + KEY_OZONE: " Ozone: {} ppb", + KEY_PRESSURE: "Pressure: {} hPa", + KEY_HUMIDITY: "Humidity: {}%", + KEY_VIRUSSCORE: " Virus: {}/10", + KEY_TIMESTAMP: "Measured: {:%H:%M:%S}", + # KEY_LASTFETCH: "Retrieved {:%H:%M:%S}", } ERROR_ICON = "❌" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..48866f7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +urllib3~=1.26.7 +requests~=2.26.0 +rumps~=0.3.0 +python-dotenv~=0.19.1 +pycryptodome +PyObjC~=7.3 +PyCocoa +logging \ No newline at end of file diff --git a/setup.py b/setup.py index b91e4f1..2928875 100644 --- a/setup.py +++ b/setup.py @@ -7,18 +7,18 @@ "iconfile": "icon.icns", "plist": { "LSUIElement": True, - "CFBundleShortVersionString": "0.1.0", + "CFBundleShortVersionString": "0.2.0", }, "packages": ["rumps"], } setup( name="AirQ", - version="0.1", + version="0.2", license="MIT", long_description=open("README.md").read(), app=APP, data_files=DATA_FILES, options={"py2app": OPTIONS}, - setup_requires=["py2app"], + setup_requires=["py2app"] ) From 74a7b60b567e81cca55e69151f8e04b2843044df Mon Sep 17 00:00:00 2001 From: dWiGhT Date: Wed, 3 Nov 2021 12:31:01 -0700 Subject: [PATCH 2/4] fix: added back bad merge stuff --- airq/app.py | 7 +++++++ airq/consts.py | 3 ++- airq/storage | Bin 0 -> 3521 bytes 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 airq/storage diff --git a/airq/app.py b/airq/app.py index 0eba2de..a848f55 100644 --- a/airq/app.py +++ b/airq/app.py @@ -82,6 +82,7 @@ def update_status(self, data): else: new_title = label.format(value) self.menu[key].title = new_title + formatted_values[key] = new_title # if key in self.warns: if warningColor == 'yellow': @@ -101,6 +102,12 @@ def update_status(self, data): string = NSAttributedString.alloc().initWithString_attributes_(new_title, attributes) self.menu[key]._menuitem.setAttributedTitle_(string) + title_format = consts.DEFAULT_TITLE_FORMAT + self.title = title_format.format( + icon=new_icon, + temp=self.strip_sensor_name(formatted_values[consts.KEY_TEMP]), + co2=self.strip_sensor_name(formatted_values[consts.KEY_CO2]) + ) @rumps.clicked("Debug") def debug(self, sender): diff --git a/airq/consts.py b/airq/consts.py index c36949b..0c11dc1 100644 --- a/airq/consts.py +++ b/airq/consts.py @@ -25,8 +25,9 @@ KEY_PRESSURE: "Pressure: {} hPa", KEY_HUMIDITY: "Humidity: {}%", KEY_VIRUSSCORE: " Virus: {}/10", + KEY_SEPARATOR: "--", KEY_TIMESTAMP: "Measured: {:%H:%M:%S}", - # KEY_LASTFETCH: "Retrieved {:%H:%M:%S}", + KEY_LASTFETCH: "Retrieved {:%H:%M:%S}", } GOOD_ICON = "☺️" diff --git a/airq/storage b/airq/storage new file mode 100644 index 0000000000000000000000000000000000000000..43425a134c88defacb90b0397620c7a276181eb6 GIT binary patch literal 3521 zcmb7GYit}>6;84buV0Cil!rnoZbgNivg?_B4^fnECwWOINZgE=cq*Ef_REQsQl*Knc1~BSRssL@65U9 zoO{ms&iU^Bdh$Cz8b1?0uZt-@#IVDt$AtVyn#f1uH8CYW#u)Z2WH*Cu8+(F(x|Hv9 zDtV<`DV0m`lnbSNRVkG#f)D#v7c(DqU9mXv(HjW-1k4XTrnZqCV9_|sQwFsu_(^Se z7(0R|OzMld8)E;1xgS3BRX!Fj&s)r=-kxYA0-p3SID|;Z=-kVzo$w)JJ$rI~?#9DH z`0!!V^047s)DcZ`LE2_W(6vm<-|N}eBh^9s-(PpX|C^EP@13&i zU%w}xxB6CzZE8dYOT%YjgM^1oA;XJPBNuo=)vF@l34`Wi&0C4VQ2zYt)W<(PdNqpv zoIxYC#+j2^@D(PPqWje8$M}iUGW&5HW2m2SdfU$3=mkGe$8Sa$MBYcXEiYhe28A*- z&IPjm=_i0sGK=qj_y!`wAy5rjfEeL{5&$S<;wiA~Rh2vwE7!+<0na;wZhsf27XwE= z6)PXTD;M4xRPLqRQ@#=^FP$5}s$YT_EAm{VweSR-$n&AjsUVTh$07Ysc*qx?;N|KG z1e8vvjA8up)k;Y%R*Pj-Q>rk2fWXK9Cjxi=6*kRaogT>soci~FA+U5>gZ(p}$6itU z2t38akO+ZBc5wfP@jkL=d*%PZWBv5@iB5g0@;@uP=kfOWiJW@(?XchD^3UCP6mjBU zO#QZyFywzdIQg1;0%>@!+Uot&~(2yA?9^8VVjNo#p+QZ43+ z*Cy8tWaF7aPEn=>zYwL7y^WlWAj%y(+4aV?2iMh{a=c!bds)tg;8!;GEjL>J;v{4k zGB129xe`PI!8u-EW=ApAcD1Tv zT+vF^P8EV5ixpeTjd~L_3ud`oQ7a|0T~NwKp^db>S}m8008$Nbqn@=N)>-h+y@HX4 zy-A46P%5a5Dw6V2VfbQW30i2=?0FOl%S7Xu5P_l?Taok3_ zO99b6!Os)lcVnYXP~n$naR&vqA6czLYJJ0ugMDTo=!yeA*w-z`^5F^syV*8mcE~RcuDi%5Ae~^?fKyv{J?c}qM?f`GvMBJI*kMe3 z3#zNPZE9>`Gme~zX^8S1}pn{5oBmoH~9R%!g!hpv&B;H~#7HaF+RppMhdH2?4cdxa&(b&Gr=G#rXx!cH- zIc2q*E799`=j-z?=5IAOD)jz6Hj53zXj$I&om-1!cK<<;$M@vw(ku5XWF08QrJgUE z{Ji|tnTrho2gd!7r{l7pk{F+e)&}%1#j;~ieDIPCF(BWC4FHT21_wMH!2(J{c-Mt1 z8iP27ObfctGiCR|+;=70H2G-!sskZOrMMZvG^K-`yi4-TJV3ha*n6VMf;MC9F|d*d zrcW9}8|=!F0-F@zvK78%z>P~CV3OAa<7pRps2eV%!+zb9sTepcRR)>J^(95ixNJLO zBKfuK0dr$>7A8Q#y9#uk2^;N8Gc$r;>`(9s2lK7gN-gqt+!3Q)vKNZYV9WcCg}-lfhl|kj1c09Y` Date: Wed, 3 Nov 2021 13:04:07 -0700 Subject: [PATCH 3/4] fix: improvement: menu bar title --- .gitignore | 1 + airq/app.py | 15 +++++++++++---- airq/consts.py | 2 +- airq/storage | Bin 3521 -> 3907 bytes 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index c2f265d..cd14fc7 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ __pycache__ build dist +airq/storage .eggs/ .idea/ AirQ.egg-info/ diff --git a/airq/app.py b/airq/app.py index a848f55..31e1b36 100644 --- a/airq/app.py +++ b/airq/app.py @@ -63,6 +63,7 @@ def update_status(self, data): # sensor values values = data[0] formatted_values = {} + warning_values = [] for key, label in consts.LABELS.items(): warningColor = None if key == consts.KEY_SEPARATOR: @@ -84,13 +85,14 @@ def update_status(self, data): self.menu[key].title = new_title formatted_values[key] = new_title - # if key in self.warns: if warningColor == 'yellow': color = NSColor.colorWithCalibratedRed_green_blue_alpha_(204/255, 204/255, 0, 1) font = NSFont.fontWithName_size_("Courier-Bold", 14.0) + warning_values = warning_values + [new_title] elif warningColor == 'red': color = NSColor.colorWithCalibratedRed_green_blue_alpha_(1, 0, 0, 1) font = NSFont.fontWithName_size_("Courier-Bold", 14.0) + warning_values = [new_title] + warning_values else: color = NSColor.colorWithCalibratedRed_green_blue_alpha_(0, 186.0/255, 44.0/255, 1) font = NSFont.fontWithName_size_("Courier", 14.0) @@ -102,11 +104,16 @@ def update_status(self, data): string = NSAttributedString.alloc().initWithString_attributes_(new_title, attributes) self.menu[key]._menuitem.setAttributedTitle_(string) + # use the major changers as the second info + warned_sensor = formatted_values[consts.KEY_DUST].replace(" ", "") + if warning_values: + warned_sensor = warning_values[0].replace(" ", "") + title_format = consts.DEFAULT_TITLE_FORMAT self.title = title_format.format( icon=new_icon, - temp=self.strip_sensor_name(formatted_values[consts.KEY_TEMP]), - co2=self.strip_sensor_name(formatted_values[consts.KEY_CO2]) + temp=self.strip_sensor_name(formatted_values[consts.KEY_TEMP].replace(" ", "").split("/")[0]), + hisensor=self.strip_sensor_name(warned_sensor) ) @rumps.clicked("Debug") @@ -118,4 +125,4 @@ def debug(self, sender): ).run() def strip_sensor_name(self, formatted_value): - return " ".join(formatted_value.split(" ")[-2:]) + return (" ".join(formatted_value.split(" ")[-2:])).replace(" ", "") diff --git a/airq/consts.py b/airq/consts.py index 0c11dc1..dec001f 100644 --- a/airq/consts.py +++ b/airq/consts.py @@ -12,7 +12,7 @@ KEY_LASTFETCH = "lastfetch" KEY_SEPARATOR = "separator" -DEFAULT_TITLE_FORMAT = "{icon} {temp} / {co2}" +DEFAULT_TITLE_FORMAT = "{icon} {temp} {hisensor}" LABELS = { KEY_CO: " CO: {} ppm", diff --git a/airq/storage b/airq/storage index 43425a134c88defacb90b0397620c7a276181eb6..fe918376ccd401999e441dee96a7b33d0137a012 100644 GIT binary patch delta 1208 zcmbu9TTIhn6vx+gV{UR$!AQV>h7dsI(sg5-hQNSk8)X;9xM)nYYdgM)TIiSo3_(py zFlhqIS54r-2TgqN!Ngz;ugWXkAobUHP=X`xs zI9sHI{W!atbaYWiVfN5Ei2ZnxBNvv8wpP{qQEbd$jpZSc!Cu7i#gq1_s!-4Q5cFiaj;| zEkkzPs6r>$mF4QFLT zT$nbo1RXYo>>S6)$}C500PsR&m>!7m@~tXvBKByYB~ zSlFJHra`8sD$sV$Q)+7D{bn{onsLh7*-v?*g5T2AJ0w{8`r6&TZr@O6XHEBTBMDax z5#%oHGG3IAnto<XBw!M*Rn^YD9~-}C-nRlle* z+}7WpFU}gS=#Fh=x#N|XV&KIgQ9_C#CJ90kDR@LoBX2Xx-mQZZx~l9_?FGkf0rNfw zlz5xhnucdTnwmfv14{k4tP~7OLMkOo0vbmaP~^Qhy%g07#`LF11<#259uO$R)JC`@ zM3B}7jc$0KmXCo_1-A`QNLFxOwC9*@(1usRS*#ICc#ToPlPUu587;6z=g_Te!fS>` z)!|tkZH6PpvdYg7wVK&?1WxW7S%hJIy(OSKAUyG(FsR<82ijFp0DJHga2~JI?Pw|u zT=(xo5?J4PIepdgC$CqY(+eCH*RS0$qIq)OTt21R^VWk2FX#Gb@$S2Otj&;nDJ{N7 zdsD#YdKUi0PQz!$5}kW%Zo&8tYjH*>g0w}VM8p=RD4QUVZYLF`2&9<%t)BK^x0UVm z(+pB791)j`w2{t8*g?2>N0@WlZIsJ(4z3kcR#0}1CrHl4k#3%{IU^3r?j|XMm@^m7 zV5%5=Vxq8{aKl7}*i@~<6S4-0Zueks+hF1b8;togy(wRq8Dg&c?Z8U}6AezWqt{3K zYVB=Ij1>F(Qmq2d^K4wobhljwt)nBdUFg%$KubRfLU5=kjy-^@MPu4zJ!T(vrYpp% zd+Mdt)7VOP&@8R4FB|k+Qg6MF_Ov49XlEDO-pTa9*Tvhn-qhdOU8x1|Huv}5e*`Qt zU}*|0Ghl@Q9~iJYjld`H1+1&k#w6IB1Y7ms>m>MQQHnV^4MZtE%BACC5@nGb2HWEZ peD|Bc5B2*wC5L6jm`Y0mmq1fWVOo+?=>Z{`L6b^x0urTV{{V8LJP-f? From c347579012201298f20d8b12d2ba49503e8f2fb5 Mon Sep 17 00:00:00 2001 From: dWiGhT Date: Wed, 3 Nov 2021 13:14:14 -0700 Subject: [PATCH 4/4] Delete storage --- airq/storage | Bin 3907 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 airq/storage diff --git a/airq/storage b/airq/storage deleted file mode 100644 index fe918376ccd401999e441dee96a7b33d0137a012..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3907 zcmd5~pzVmbM*P`DoP7e9c8+?WhJJ@un?QroERgsJM>wHH1j62xYkx}#7O>A@a zY%Z;7g>))k$mMhJ)`j4fWPI~nni@vb~M zvv~D`4@a+9KlqTHR&^UIu1-x}Ba=dQgm`UT)!j~4zH;Y#@O*zz{ug5F{RiZHSIV-n z<9IgiO5J^e3wkJs3d1f++z`i zrbE`H$e`AbUYmLJ(|fN4=0By-fUP>z&jo+JcQLw8&7P6Z2+xkY_FhQz`6Fg`+r_KD z4xsN>yLk1R0SJNi(H-6PoDGFS9I8)w0)Y5q&?h4+&jRM;w2xF(L?DD%#DMo{CR1H7 zHUAmp{J;k|(+w+mI%Hn>(Fx2y_aj^HF@H8>eiFdQ1)q5}^?0zz#ei+$F+h>$eV!9h zB3}w^dM0#iATIs*kS_)MX<8mb9j1$goRlqQ^HM2QggOKyN_|Ki zv%8m#P#;G~#7_wBgD`i(vIvo=zA}i{A0b<39{ub;A-FHZk5$^kV=4m(s$U#bc^`^- z^vbrMhTZVLIgn7@a6C!epL<_C_XoH5iP*vVVX#Fv?w_2**Yf;1jw2dB zn?kz1okW(N6e9$+FlS?%OO$Se4Bz3iUl&c44HJx198SD=Sy8a%!Z^A#cZsv;5{1D9 zx;&R8JwmB&DoKU5Ih$D45;f?$iB;q(gtO1TI`=}ZlrYTA@_u^jrLWu}jnv({>dGyt zW0YUuYGL@R;Y%*{oaRZqxFYq0k ziOuTe?JH6;b+ld)d+BD2vkR?#-3pdpo(2#7(FgyjWDYC==QZ%Wg6`RGZCS?m!DU(m96bNO=*jTGpYQTvK*>nmQ z)F#$YTFoFW-7I0O0Ov#*aHF=q@5h<5FI>mS#`d(N6w{iTR#XKyvzZ*q7cx04NjVtF z!wRKaI(7hb8*h7XjBx<)kaV^llIDHN3bOf88p##~L_3_FA+BqMLU)0MonHXUJi`s7 z)&sVl;E0J`M?sJk2W;5ZlyoVd@v5898!~qsGRGu3|Z`C=F~Aj%(|RE334P zbQ1`l3kjhn*)wcl&5H z7L`r9%U3i}-Ay(UdM=KqCsZX6PtA#?5mBp2M~8#gn=Bs0y$>pgh~Ff@!KjI#d-Msg z@QBLl&Wo9HeGg}(%o8Ri#Im_BuUc0^4xpgabd;dD5b=0D^%WLe6c*~B36@Uhc{gB1Opr7Ct zn+nzj_|Jv3BS>7(67>-vKZXqeiavn@77suHreVBi!3o&`JBC#qa?e&p?m^YJMX#x` zvG7xdb|jd>R0PqO407Tq&qkI2&^6QO@S5W_9mhEaRTM$(31LWrJyB2~69ZJX{I3yE zV^I_O$m`r;aSPd~?JvarZ0!hF6zqp;1gXe!MS~W08Ai~D#NV0?eH*I_kpBYQIyCbU zKh0j5o8#B4V(dgTO+?aBp=nt?`z~?jeLBMlTXN}