Skip to content

Commit f53b7f1

Browse files
committed
- switch acaia COSMO to streaming mode
- RoastHubs profile upload respecting current curve smoothing settings - fixed size login dialogs - adds Artisan Commands `zoom(<x>[,<y>])`, `pan(<x>[,<y>])`, `center(<x>,<y>[,<clamp>])`, `clamp(<n>)`, `followMode(<bool>)`, and `followModePanning(<x>[,<y>])` to update the canvas perspective - adds Artisan Commands `home`, `back` and `forward` to operate the navigation bar - improved PID buttons layout - updated icons and translations - lib updates
1 parent 0f31b71 commit f53b7f1

88 files changed

Lines changed: 202264 additions & 200468 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
1.08 KB
Binary file not shown.

doc/help_dialogs/Output_html/eventbuttons_help.html

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,51 @@
982982
<td>upload2RoastHubs</td>
983983
<td>upload current loaded profile to RoastHubs</td>
984984
</tr>
985+
<tr>
986+
<td>&#160;</td>
987+
<td>zoom(&lt;x&gt;[,&lt;y&gt;])</td>
988+
<td>zooms the canvas by factor &lt;x&gt; horizontally and the optional &lt;y&gt; vertically. &lt;y&gt; defaults to &lt;x&gt;.</td>
989+
</tr>
990+
<tr>
991+
<td>&#160;</td>
992+
<td>pan(&lt;x&gt;[,&lt;y&gt;])</td>
993+
<td>pans the canvas by factor &lt;x&gt; horizontally and the optional &lt;y&gt; vertically. A factor 0 does not apply any panning, a factor 1 moves by one full screen to the left/bottom, a factor -1 by one full screen to the right/top. &lt;y&gt; defaults to &lt;x&gt;.</td>
994+
</tr>
995+
<tr>
996+
<td>&#160;</td>
997+
<td>center(&lt;x&gt;,&lt;y&gt;[,&lt;clamp&gt;])</td>
998+
<td>centers canvas and then applies panning according to the given x/y parameters in horizontal and vertical direction. 0: no panning, 1: pan canvas one full screen to the left/bottom, -1: pan canvas one full screen to the right/top. If &lt;clamp&gt; is 0 the canvas is centered w.r.t. both axis limits. If not recording, and &lt;clamp&gt; i -1 the canvas is centered only horizontally wr.t. its x-axis limits and with clamp in {1,..,4} w.r.t. to both axis limits. While recording if &lt;clamp&gt; is -1 the canvas is centered horizontally to the current time, if 1 also centered to current BT, 2 current ET, 3 current BT RoR, 4 current ET RoR. &lt;clamp&gt; defaults to -1 if xy-cursor widget is clamped to any temp or RoR curve (z-key), 0 if zoom follow is OFF and xy-cursor not clamped, 1-4 if zoom follow is ON and xy-cursor not clamped, centering on the value zoom followed.</td>
999+
</tr>
1000+
<tr>
1001+
<td>&#160;</td>
1002+
<td>clamp(&lt;n&gt;)</td>
1003+
<td>set xy cursor clamp mode (shortcut key z) to 0: off, 1: BT@x, 2: ET@x, 3: BTB@x, 4: ETB@x</td>
1004+
</tr>
1005+
<tr>
1006+
<td>&#160;</td>
1007+
<td>followMode(&lt;bool&gt;)</td>
1008+
<td>enables/disables follow mode</td>
1009+
</tr>
1010+
<tr>
1011+
<td>&#160;</td>
1012+
<td>followModePanning(&lt;x&gt;[,&lt;y&gt;])</td>
1013+
<td>sets additional panning in horizontal and vertical direction, applied in follow mode after the centering. 0: no panning, 1: pan canvas one full screen to the left/bottom, -1: pan canvas one full screen to the right/top. &lt;y&gt; defaults to &lt;x&gt;.</td>
1014+
</tr>
1015+
<tr>
1016+
<td>&#160;</td>
1017+
<td>home</td>
1018+
<td>toolbar home action</td>
1019+
</tr>
1020+
<tr>
1021+
<td>&#160;</td>
1022+
<td>back</td>
1023+
<td>toolbar back action</td>
1024+
</tr>
1025+
<tr>
1026+
<td>&#160;</td>
1027+
<td>forward</td>
1028+
<td>toolbar forward action</td>
1029+
</tr>
9851030
<tr>
9861031
<td>RC Command</td>
9871032
<td>pulse(ch,min,max[,sn])</td>

src/README.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Artisan is free for personal and commercial use, but asks for a [donation](https
66

77
<https://artisan-scope.org>
88

9-
The home of its development is on GitHub were all source and binary files are available as well as an issue tracker.
9+
The home of its development is on GitHub where all source and binary files are available as well as an issue tracker.
1010

1111
<https://github.com/artisan-roaster-scope/artisan>
1212

src/artisanlib/acaia.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ class ACAIA_TIMER(IntEnum):
236236

237237
HEARTBEAT_FREQUENCY:Final[int] = 5 # send the heartbeat every 5 sec
238238

239-
RELAY_STREAMING:Final[bool] = False # if set, configure Acaia relay (and COSMO) scales to streaming mode, otherwise they work in non-streaming mode reporting only weight changes
239+
RELAY_STREAMING:Final[bool] = True # if set, configure Acaia relay (and COSMO) scales to streaming mode, otherwise they work in non-streaming mode reporting only weight changes
240240
WEIGHT_ROUNDING:Final[bool] = False # if set, received weights are rounded to appropriate values based on scales readability
241241
# rounding for scales with readability>1 (to 4g), no rounding otherwise
242242

src/artisanlib/canvas.py

Lines changed: 185 additions & 25 deletions
Large diffs are not rendered by default.

src/artisanlib/main.py

Lines changed: 164 additions & 38 deletions
Large diffs are not rendered by default.

src/artisanlib/pid_control.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,20 +1842,10 @@ def activateSVSlider(self, flag:bool) -> None:
18421842

18431843
def showSVButtons(self) -> None:
18441844
if self.aw.qmc.flagon and self.aw.qmc.Controlbuttonflag:
1845-
self.aw.buttonSVp5.setVisible(True)
1846-
self.aw.buttonSVp10.setVisible(True)
1847-
self.aw.buttonSVp20.setVisible(True)
1848-
self.aw.buttonSVm20.setVisible(True)
1849-
self.aw.buttonSVm10.setVisible(True)
1850-
self.aw.buttonSVm5.setVisible(True)
1845+
self.aw.pidbuttonFrame.setVisible(True)
18511846

18521847
def hideSVButtons(self) -> None:
1853-
self.aw.buttonSVp5.setVisible(False)
1854-
self.aw.buttonSVp10.setVisible(False)
1855-
self.aw.buttonSVp20.setVisible(False)
1856-
self.aw.buttonSVm20.setVisible(False)
1857-
self.aw.buttonSVm10.setVisible(False)
1858-
self.aw.buttonSVm5.setVisible(False)
1848+
self.aw.pidbuttonFrame.setVisible(False)
18591849

18601850
def activateONOFFeasySV(self, flag:bool) -> None:
18611851
if flag:

src/artisanlib/roast_properties.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ def __init__(self, parent:'editGraphDlg', aw:'ApplicationWindow', weightIn:float
164164
self.coffeeinweight.setReadOnly(True)
165165
self.coffeeinweight.setFocusPolicy(Qt.FocusPolicy.NoFocus)
166166
if sys.platform.startswith('darwin'):
167-
self.coffeeinweight.setStyleSheet("border: 0.5px solid lightgrey; background-color:'lightgrey'")
167+
#self.coffeeinweight.setStyleSheet("border: 0.5px solid lightgrey; background-color:'lightgrey'")
168+
pass
168169
else:
169170
self.coffeeinweight.setStyleSheet("background-color:'lightgrey'")
170171
coffeeinweightUnit = QLabel(weight_units[weightunit])
@@ -236,7 +237,8 @@ def __init__(self, parent:'editGraphDlg', aw:'ApplicationWindow', weightIn:float
236237
self.coffeeoutweight.setAlignment(Qt.AlignmentFlag.AlignRight)
237238
self.coffeeoutweight.setReadOnly(True)
238239
if sys.platform.startswith('darwin'):
239-
self.coffeeoutweight.setStyleSheet("border: 0.5px solid lightgrey; background-color:'lightgrey'")
240+
# self.coffeeoutweight.setStyleSheet("border: 0.5px solid lightgrey; background-color:'lightgrey'")
241+
pass
240242
else:
241243
self.coffeeoutweight.setStyleSheet("background-color:'lightgrey'")
242244
self.coffeeoutweight.setFocusPolicy(Qt.FocusPolicy.NoFocus)
@@ -2200,21 +2202,23 @@ def markPlusCoffeeFields(self, b:bool) -> None:
22002202

22012203

22022204
# for QLineEdit
2203-
if b:
2204-
if self.aw.app.darkmode:
2205-
qlineedit_marked_style = 'QLineEdit { background-color: #0D658F; selection-background-color: darkgray; }'
2205+
# not on macOS as there seems to be an interaction between the native and Qt widget
2206+
if not sys.platform.startswith('darwin'):
2207+
if b:
2208+
if self.aw.app.darkmode:
2209+
qlineedit_marked_style = 'QLineEdit { background-color: #0D658F; selection-background-color: darkgray; }'
2210+
else:
2211+
qlineedit_marked_style = 'QLineEdit { background-color: #e4f3f8; selection-background-color: #424242; }'
2212+
self.bean_density_in_edit.setStyleSheet(qlineedit_marked_style)
2213+
self.bean_size_min_edit.setStyleSheet(qlineedit_marked_style)
2214+
self.bean_size_max_edit.setStyleSheet(qlineedit_marked_style)
2215+
self.moisture_greens_edit.setStyleSheet(qlineedit_marked_style)
22062216
else:
2207-
qlineedit_marked_style = 'QLineEdit { background-color: #e4f3f8; selection-background-color: #424242; }'
2208-
self.bean_density_in_edit.setStyleSheet(qlineedit_marked_style)
2209-
self.bean_size_min_edit.setStyleSheet(qlineedit_marked_style)
2210-
self.bean_size_max_edit.setStyleSheet(qlineedit_marked_style)
2211-
self.moisture_greens_edit.setStyleSheet(qlineedit_marked_style)
2212-
else:
2213-
background_white_style = ''
2214-
self.bean_density_in_edit.setStyleSheet(background_white_style)
2215-
self.bean_size_min_edit.setStyleSheet(background_white_style)
2216-
self.bean_size_max_edit.setStyleSheet(background_white_style)
2217-
self.moisture_greens_edit.setStyleSheet(background_white_style)
2217+
background_white_style = ''
2218+
self.bean_density_in_edit.setStyleSheet(background_white_style)
2219+
self.bean_size_min_edit.setStyleSheet(background_white_style)
2220+
self.bean_size_max_edit.setStyleSheet(background_white_style)
2221+
self.moisture_greens_edit.setStyleSheet(background_white_style)
22182222

22192223
def updateTitle(self, prev_coffee_label:str|None, prev_blend_label:str|None) -> None:
22202224
titles_to_be_overwritten = [ '', QApplication.translate('Scope Title', 'Roaster Scope') ]
@@ -4934,13 +4938,14 @@ def deleteEventTable(self, _:bool = False) -> None:
49344938

49354939
# mark widget w if b holds otherwise unmark it
49364940
def markWidget(self, w:QLineEdit, b:bool) -> None:
4937-
if b:
4938-
if self.aw.app.darkmode:
4939-
w.setStyleSheet("""QLineEdit { background-color: #ad0427; }""")
4941+
if not sys.platform.startswith('darwin'):
4942+
if b:
4943+
if self.aw.app.darkmode:
4944+
w.setStyleSheet("""QLineEdit { background-color: #ad0427; }""")
4945+
else:
4946+
w.setStyleSheet("""QLineEdit { color: #CC0F50; }""")
49404947
else:
4941-
w.setStyleSheet("""QLineEdit { color: #CC0F50; }""")
4942-
else:
4943-
w.setStyleSheet('QLineEdit { }')
4948+
w.setStyleSheet('QLineEdit { }')
49444949

49454950
def checkWeightOut(self) -> None:
49464951
try:

src/artisanlib/roasthubs.py

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
from proto import artisan_roast_pb2 # pylint: disable=unused-import
4242

4343
from PyQt6.QtWidgets import (QApplication, QGroupBox, QHBoxLayout,
44-
QVBoxLayout, QLabel, QLineEdit, QDialogButtonBox)
44+
QVBoxLayout, QLabel, QLineEdit, QDialogButtonBox, QLayout)
4545
from PyQt6.QtCore import Qt, pyqtSlot
4646
from PyQt6.QtGui import QKeySequence, QAction
4747

@@ -105,11 +105,47 @@ async def send_roast(roast:'artisan_roast_pb2.Roast', token:str,
105105
_log.error('exception in roasthubs:send_roast: %s', e)
106106

107107

108-
def send_profile(profile:'ProfileData', org_id:str, machine_id:str, token:str,
109-
on_success:Callable[[], None] | None, on_failure:Callable[[], None] | None) -> None:
108+
def send_profile(
109+
profile:'ProfileData',
110+
org_id:str,
111+
machine_id:str,
112+
token:str,
113+
# filter conf
114+
interpolate_drops:bool = True,
115+
curvefilter:int = 3,
116+
medfilt_factor:int = 3,
117+
limit_ror:bool = True,
118+
ror_limit_min:int = 0,
119+
ror_limit_max:int = 170,
120+
delta_span_ET:int = 20,
121+
delta_span_BT:int = 20,
122+
medfilt_factor_RoR:int = 3,
123+
delta_ET_filter:int = 7,
124+
delta_BT_filter:int = 7,
125+
# handlers
126+
on_success:Callable[[], None] | None = None,
127+
on_failure:Callable[[], None] | None = None) -> None:
110128
if org_id != '' and machine_id != '' and token != '':
111129
# only if org_id and machin_id are not empty the connector is active
112-
roast:artisan_roast_pb2.Roast|None = roast_message(profile, org_id=org_id, machine_id=machine_id) # pylint: disable=no-member
130+
roast:artisan_roast_pb2.Roast|None = roast_message( # pylint: disable=no-member
131+
profile,
132+
org_id=org_id,
133+
machine_id=machine_id,
134+
# filter conf
135+
interpolate_drops=interpolate_drops,
136+
smooth_curves=True,
137+
curvefilter=curvefilter,
138+
medfilt_factor=medfilt_factor,
139+
decay_smoothing_p=False, # optimal smoothing # qmc.optimalSmoothing
140+
limit_ror=limit_ror,
141+
ror_limit_min=ror_limit_min,
142+
ror_limit_max=ror_limit_max,
143+
delta_span_ET=delta_span_ET,
144+
delta_span_BT=delta_span_BT,
145+
medfilt_factor_RoR=medfilt_factor_RoR,
146+
delta_ET_filter=delta_ET_filter,
147+
delta_BT_filter=delta_BT_filter
148+
) # pylint: disable=no-member
113149
if roast is not None:
114150
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
115151
executor.submit(asyncio.run, send_roast(roast, token, on_success, on_failure))
@@ -228,7 +264,10 @@ def __init__(self, aw:'ApplicationWindow') -> None:
228264
layout.addLayout(buttonLayout)
229265
layout.setContentsMargins(10, 10, 10, 10)
230266
layout.setSpacing(5)
231-
self.setLayout(layout)
267+
268+
# not resizable
269+
layout.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize)
270+
self.setSizeGripEnabled(False)
232271

233272

234273
@pyqtSlot(str)

src/artisanlib/roest.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
if TYPE_CHECKING:
3535
from artisanlib.main import ApplicationWindow # noqa: F401 # pylint: disable=unused-import
3636

37-
from PyQt6.QtWidgets import (QApplication, QGroupBox, QHBoxLayout,
37+
from PyQt6.QtWidgets import (QApplication, QGroupBox, QHBoxLayout, QLayout,
3838
QVBoxLayout, QLabel, QLineEdit, QToolButton, QDialogButtonBox, QComboBox)
3939
from PyQt6.QtCore import Qt, pyqtSlot
4040
from PyQt6.QtGui import QKeySequence, QAction, QIcon
@@ -543,7 +543,10 @@ def __init__(self, aw:'ApplicationWindow', client_id:str, client_secret:str) ->
543543
layout.addLayout(buttonLayout)
544544
layout.setContentsMargins(10, 10, 10, 10)
545545
layout.setSpacing(5)
546-
self.setLayout(layout)
546+
547+
# not resizable
548+
layout.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize)
549+
self.setSizeGripEnabled(False)
547550

548551
@pyqtSlot(str)
549552
def textChanged(self, _:str) -> None:

0 commit comments

Comments
 (0)