diff --git a/.appveyor.yml b/.appveyor.yml index 7aaaffa61..f9f72e3ca 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -20,7 +20,7 @@ environment: # Set the Appveyor Python version for windows, macos and linux here. Does not affect windows_legacy. PYTHON_V: 3.11 # Upgrade to specific version (for platforms supporting upgrade). Upgrade skipped if env var is missing or blank. - PYUPGRADE_V: 3.11.5 +# PYUPGRADE_V: 3.11.5 # causes ssl problems failing to connect to plus matrix: - job_name: windows_legacy diff --git a/src/artisanlib/canvas.py b/src/artisanlib/canvas.py index 988c618f2..516c075c9 100644 --- a/src/artisanlib/canvas.py +++ b/src/artisanlib/canvas.py @@ -3304,7 +3304,7 @@ def update_additional_artists(self) -> None: linestyle = '-', linewidth= 1, alpha = .5,sketch_params=None,path_effects=[]) else: self.l_timeline.set_xdata(tx) - self.ax.draw_artist(self.l_timeline) + self.ax.draw_artist(self.l_timeline) if self.projectFlag: if self.l_BTprojection is not None and self.BTcurve: self.ax.draw_artist(self.l_BTprojection) @@ -6673,6 +6673,8 @@ def reset(self,redraw=True,soundOn=True,sampling=False,keepProperties=False,fire self.l_event_flags_dict = {} # initiate the event id to temp/time annotation dict for flags self.l_background_annotations = [] # initiate the background event annotations + self.l_timeline = None # clear timeline Artist to get the linecount correct after changning a machine setup + if not sampling: self.aw.hideDefaultButtons() self.aw.updateExtraButtonsVisibility() diff --git a/src/artisanlib/curves.py b/src/artisanlib/curves.py index 250025758..46888cd9c 100644 --- a/src/artisanlib/curves.py +++ b/src/artisanlib/curves.py @@ -1504,16 +1504,16 @@ def renameBT(self): self.aw.BTname = str(self.renameBTLine.text()).strip() if self.aw.BTname == '': self.aw.BTname = QApplication.translate('Label', 'BT') - self.aw.label3.setText('' + self.aw.BTname + '') - self.aw.label5.setText(deltaLabelBigPrefix + self.aw.BTname + '') + self.aw.label3.setText(f'{self.aw.BTname}'.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])) + self.aw.label5.setText(f'{deltaLabelBigPrefix}{self.aw.BTname}'.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])) @pyqtSlot() def renameET(self): self.aw.ETname = str(self.renameETLine.text()).strip() if self.aw.ETname == '': self.aw.ETname = QApplication.translate('Label', 'ET') - self.aw.label2.setText('' + self.aw.ETname + '') - self.aw.label4.setText(deltaLabelBigPrefix + self.aw.ETname + '') + self.aw.label2.setText(f'{self.aw.ETname}'.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])) + self.aw.label4.setText(f'{deltaLabelBigPrefix}{self.aw.ETname}'.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])) @pyqtSlot(int) def toggleWebLCDsAlerts(self,_): @@ -1526,7 +1526,7 @@ def changeWebLCDsPort(self): def setWebLCDsURL(self): url_str = self.getWebLCDsURL() # set URL label - self.WebLCDsURL.setText('' + url_str + '') + self.WebLCDsURL.setText(f'{url_str}') # set QR label try: from artisanlib.qrcode import QRlabel @@ -1541,7 +1541,7 @@ def getWebLCDsURL(self): s.connect(('8.8.8.8', 80)) localIP = s.getsockname()[0] s.close() - return 'http://' + str(localIP) + ':' + str(self.aw.WebLCDsPort) + '/artisan' + return f'http://{str(localIP)}:{str(self.aw.WebLCDsPort)}/artisan' @pyqtSlot(bool) def toggleWebLCDs(self,b): diff --git a/src/artisanlib/large_lcds.py b/src/artisanlib/large_lcds.py index 8306e317a..a842f6d5a 100644 --- a/src/artisanlib/large_lcds.py +++ b/src/artisanlib/large_lcds.py @@ -361,7 +361,7 @@ def makeLCDs(self): self.lcd0.display('00:00') # ET ETlcd = self.makeLCD('et') # Environmental Temperature ET - ETlabelUpper = self.makeLabel('' + self.aw.ETname + ' ') + ETlabelUpper = self.makeLabel(f'{self.aw.ETname.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])} ') ETlabelLower = self.makeLabel(' ') # self.lcds1 = [ETlcd] @@ -371,7 +371,7 @@ def makeLCDs(self): self.lcds1frames = [self.makeLCDframe(ETlabelUpper,ETlcd,ETlabelLower)] # BT BTlcd = self.makeLCD('bt') # Bean Temperature BT - BTlabelUpper = self.makeLabel('' + self.aw.BTname + ' ') + BTlabelUpper = self.makeLabel(f'{self.aw.BTname.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])} ') BTlabelLower = self.makeLabel(' ') # self.lcds2 = [BTlcd] @@ -490,7 +490,7 @@ def __init__(self, parent = None, aw = None) -> None: def makeLCDs(self): self.lcds1styles = ['deltaet'] self.lcds1 = [self.makeLCD(self.lcds1styles[0])] # DeltaET - label1Upper = self.makeLabel('Δ' + self.aw.ETname + ' ') + label1Upper = self.makeLabel(f'Δ{self.aw.ETname.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])} ') label1Lower = self.makeLabel(' ') self.lcds1labelsUpper = [label1Upper] self.lcds1labelsLower = [label1Lower] @@ -498,7 +498,7 @@ def makeLCDs(self): # self.lcds2styles = ['deltabt'] self.lcds2 = [self.makeLCD(self.lcds2styles[0])] # DeltaBT - label2Upper = self.makeLabel('Δ' + self.aw.BTname + ' ') + label2Upper = self.makeLabel(f'Δ{self.aw.BTname.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])} ') label2Lower = self.makeLabel(' ') self.lcds2labelsUpper = [label2Upper] self.lcds2labelsLower = [label2Lower] diff --git a/src/artisanlib/main.py b/src/artisanlib/main.py index 8cae34098..4f916193a 100644 --- a/src/artisanlib/main.py +++ b/src/artisanlib/main.py @@ -3175,31 +3175,31 @@ def __init__(self, parent:Optional[QWidget] = None, *, locale:str, WebEngineSupp #MET self.label2 = QLabel() self.label2.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight) - self.label2.setText('' + QApplication.translate('Label', 'ET') + '') + self.label2.setText(f"{QApplication.translate('Label', 'ET')}") self.setLabelColor(self.label2,QColor(self.qmc.palette['et'])) #BT self.label3 = QLabel() self.label3.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight) - self.label3.setText('' + QApplication.translate('Label', 'BT') + '') + self.label3.setText(f"{QApplication.translate('Label', 'BT')}") self.setLabelColor(self.label3,QColor(self.qmc.palette['bt'])) #DELTA MET self.label4 = QLabel() self.label4.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight) - self.label4.setText(deltaLabelBigPrefix + QApplication.translate('Label', 'ET') + '') + self.label4.setText(f"{deltaLabelBigPrefix}{QApplication.translate('Label', 'ET')}") self.setLabelColor(self.label4,QColor(self.qmc.palette['deltaet'])) # DELTA BT self.label5 = QLabel() self.label5.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight) - self.label5.setText(deltaLabelBigPrefix + QApplication.translate('Label', 'BT') + '') + self.label5.setText(f"{deltaLabelBigPrefix}{QApplication.translate('Label', 'BT')}") self.setLabelColor(self.label5,QColor(self.qmc.palette['deltabt'])) # pid sv self.label6 = QLabel() self.label6.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight) - self.label6.setText('' + QApplication.translate('Label', 'PID SV') + '') + self.label6.setText(f"{QApplication.translate('Label', 'PID SV')}") # pid power % duty cycle self.label7 = QLabel() self.label7.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight) - self.label7.setText('' + QApplication.translate('Label', 'PID %') + '') + self.label7.setText(f"{QApplication.translate('Label', 'PID %')}") #extra LCDs self.nLCDS: Final[int] = 10 # maximum number of LCDs and extra devices @@ -4989,6 +4989,12 @@ def recentRoastsMenuList(self): return [self.recentRoastLabel(rr) for rr in self.recentRoasts] def establish_etypes(self): + # update ET/BT LCD label substitutions + self.label2.setText(f'{self.ETname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3])) + self.label3.setText(f'{self.BTname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3])) + # update ET/BT Delta LCD lable substitutions + self.label4.setText(f'{deltaLabelBigPrefix}{self.ETname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3])) + self.label5.setText(f'{deltaLabelBigPrefix}{self.BTname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3])) # update extra LCD label substitutions for i in range(len(self.qmc.extradevices)): if i < len(self.qmc.extraname1): @@ -16173,17 +16179,16 @@ def settingsLoad(self, filename=None, theme=False, machine=False, redraw=True): self.qmc.eventsGraphflag = toInt(settings.value('eventsGraphflag',int(self.qmc.eventsGraphflag))) if settings.contains('etypes'): self.qmc.etypes = toStringList(settings.value('etypes',self.qmc.etypes)) + # etype specified as empty strings are replaced by their defaults to enable translations in partially customized etypes + for i, name in enumerate(self.qmc.etypes): + if name == '': + self.qmc.etypes[i] = self.qmc.etypesdefault[i] # update minieditor event type ComboBox self.etypeComboBox.clear() self.etypeComboBox.addItems(self.qmc.etypes) else: # etypes have not been saved in the setting to presever the translations, we have to reset those to their default - self.qmc.etypes = [ - QApplication.translate('ComboBox', 'Air'), - QApplication.translate('ComboBox', 'Drum'), - QApplication.translate('ComboBox', 'Damper'), - QApplication.translate('ComboBox', 'Burner') - ] + self.qmc.etypes = self.qmc.etypesdefault self.qmc.eventsshowflag = toInt(settings.value('eventsshowflag',int(self.qmc.eventsshowflag))) self.qmc.clampEvents = bool(toBool(settings.value('clampEvents',self.qmc.clampEvents))) self.qmc.renderEventsDescr = bool(toBool(settings.value('renderEventsDescr',self.qmc.renderEventsDescr))) @@ -16773,14 +16778,14 @@ def settingsLoad(self, filename=None, theme=False, machine=False, redraw=True): self.qmc.graphfont = toInt(settings.value('graphfont',self.qmc.graphfont)) if settings.contains('ETname'): self.ETname = settings.value('ETname') - self.label2.setText('' + self.ETname + '') - self.label4.setText(deltaLabelBigPrefix + self.ETname + '') + self.label2.setText(f'{self.ETname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3])) + self.label4.setText(f'{deltaLabelBigPrefix}{self.ETname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3])) else: self.ETname = QApplication.translate('Label', 'ET') if settings.contains('BTname'): self.BTname = settings.value('BTname') - self.label3.setText('' + self.BTname + '') - self.label5.setText(deltaLabelBigPrefix + self.BTname + '') + self.label3.setText(f'{self.BTname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3])) + self.label5.setText(f'{deltaLabelBigPrefix}{self.BTname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3])) else: self.BTname = QApplication.translate('Label', 'BT') settings.endGroup() @@ -18026,7 +18031,12 @@ def saveAllSettings(self, settings:QSettings, default_settings:Optional[Dict[str (self.qmc.etypes[1] != QApplication.translate('ComboBox', 'Drum')) or (self.qmc.etypes[2] != QApplication.translate('ComboBox', 'Damper')) or (self.qmc.etypes[3] != QApplication.translate('ComboBox', 'Burner'))): - self.settingsSetValue(settings, default_settings, 'etypes',self.qmc.etypes, read_defaults) + etypes = self.qmc.etypes + if not read_defaults: + for i, _ in enumerate(self.qmc.etypes): + if self.qmc.etypes[i] == self.qmc.etypesdefault[i]: + etypes[i] = '' # we save empty strings for default event type names to ensure correct translation on re-loading those settings + self.settingsSetValue(settings, default_settings, 'etypes',etypes, read_defaults) else: settings.remove('etypes') self.settingsSetValue(settings, default_settings, 'eventsshowflag',self.qmc.eventsshowflag, read_defaults) diff --git a/src/includes/Machines/Buehler/RM_20_Legacy.aset b/src/includes/Machines/Buehler/RM_20_Legacy.aset index b60857670..38e3f36fd 100644 --- a/src/includes/Machines/Buehler/RM_20_Legacy.aset +++ b/src/includes/Machines/Buehler/RM_20_Legacy.aset @@ -1,11 +1,17 @@ [General] Delay=1000 Oversampling=false -roastertype_setup=B\xfchler Roastmaster +roastertype_setup=B\xfchler RM 20 Legacy + +[MachineSetup] +capacity=20 [Device] id=79 +[Style] +ETname=IT + [ExtraComm] extrabaudrate=19200, 19200 extrabytesize=8, 8 @@ -15,17 +21,17 @@ extrastopbits=1, 1 extratimeout=1, 1 [ExtraDev] -extraCurveVisibility1=true, false, true, true, true, true, true, true, true, true +extraCurveVisibility1=false, false, true, true, true, true, true, true, true, true extraCurveVisibility2=true, false, true, true, true, true, true, true, true, true extraLCDvisibility1=true, true, false, false, false, false, false, false, false, false extraLCDvisibility2=true, true, false, false, false, false, false, false, false, false -extradevicecolor1=black, black -extradevicecolor2=black, black +extradevicecolor1=#d27d1c, #49b260 +extradevicecolor2=#333333, #45a6cf extradevices=80, 81 extramathexpression1=, extramathexpression2=, -extraname1=AT, Speed -extraname2=Drum, Air +extraname1=AT, {1} +extraname2=Pa, {0} [S7] PID_OFF_action= @@ -47,6 +53,19 @@ port=102 rack=0 slot=1 start=16, 12, 32, 20, 8, 24, 0, 0, 0, 0 -type=1, 1, 1, 1, 1, 1, 0, 0, 0, 0 +type=1, 1, 1, 1, 2, 2, 0, 0, 0, 0 optimizer=true fetch_max_blocks=true + +[Sliders] +eventsliderunits=%, %, , + +[Quantifiers] +clusterEventsFlag=false +eventquantifierSV=0, 0, 0, 0 +eventquantifieraction=0, 0, 0, 0 +quantifieractive=1, 1, 0, 0 +quantifiercoarse=0, 0, 0, 0 +quantifiermax=100, 100, 100, 100 +quantifiermin=0, 0, 0, 0 +quantifiersource=5, 4, 0, 0 \ No newline at end of file diff --git a/src/includes/Machines/Buehler/RM_20_Playone.aset b/src/includes/Machines/Buehler/RM_20_Playone.aset new file mode 100644 index 000000000..25187c0ee --- /dev/null +++ b/src/includes/Machines/Buehler/RM_20_Playone.aset @@ -0,0 +1,71 @@ +[General] +Delay=1000 +Oversampling=false +roastertype_setup=B\xfchler RM Playone + +[MachineSetup] +capacity=20 + +[Device] +id=79 + +[Style] +ETname=IT + +[ExtraComm] +extrabaudrate=19200, 19200 +extrabytesize=8, 8 +extracomport=COM1, COM1 +extraparity=E, E +extrastopbits=1, 1 +extratimeout=1, 1 + +[ExtraDev] +extraCurveVisibility1=false, false, true, true, true, true, true, true, true, true +extraCurveVisibility2=true, false, true, true, true, true, true, true, true, true +extraLCDvisibility1=true, true, false, false, false, false, false, false, false, false +extraLCDvisibility2=true, true, false, false, false, false, false, false, false, false +extradevicecolor1=#d27d1c, #49b260 +extradevicecolor2=#333333, #45a6cf +extradevices=80, 81 +extramathexpression1=, +extramathexpression2=, +extraname1=AT, {1} +extraname2=Pa, {0} + +[S7] +PID_OFF_action= +PID_ON_action= +PID_SV_register=0 +PID_area=0 +PID_d_register=0 +PID_db_nr=0 +PID_i_register=0 +PID_p_register=0 +PIDmultiplier=0 +SVmultiplier=0 +area=6, 6, 6, 6, 6, 6, 0, 0, 0, 0 +db_nr=1606, 1606, 1606, 1606, 1606, 1606, 1, 1, 1, 1 +div=0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +host=192.168.1.10 +mode=1, 1, 1, 0, 0, 0, 0, 0, 0, 0 +port=102 +rack=0 +slot=1 +start=240, 244, 252, 248,228, 232, 0, 0, 0, 0 +type=1, 1, 1, 1, 2, 2, 0, 0, 0, 0 +optimizer=true +fetch_max_blocks=true + +[Sliders] +eventsliderunits=%, %, , + +[Quantifiers] +clusterEventsFlag=false +eventquantifierSV=0, 0, 0, 0 +eventquantifieraction=0, 0, 0, 0 +quantifieractive=1, 1, 0, 0 +quantifiercoarse=0, 0, 0, 0 +quantifiermax=100, 100, 100, 100 +quantifiermin=0, 0, 0, 0 +quantifiersource=5, 4, 0, 0 \ No newline at end of file diff --git a/src/includes/Machines/Buehler/RM_60-240.aset b/src/includes/Machines/Buehler/RM_60-240.aset new file mode 100644 index 000000000..8b420f9d4 --- /dev/null +++ b/src/includes/Machines/Buehler/RM_60-240.aset @@ -0,0 +1,71 @@ +[General] +Delay=1000 +Oversampling=false +roastertype_setup=B\xfchler RM 60-240 OC + +[Device] +id=79 + +[Style] +ETname=IT + +[ExtraComm] +extrabaudrate=19200, 19200, 19200 +extrabytesize=8, 8, 8 +extracomport=COM1, COM1, COM1 +extraparity=E, E, E +extrastopbits=1, 1, 1 +extratimeout=0.3, 0.3, 0.3 + +[ExtraDev] +extraCurveVisibility1=false, false, false, true, true, true, true, true, true, true +extraCurveVisibility2=true, false, false, true, true, true, true, true, true, true +extraLCDvisibility1=true, true, true, false, false, false, false, false, false, false +extraLCDvisibility2=true, true, true, false, false, false, false, false, false, false +extradevicecolor1=#d27d1c, #49b260, #333333 +extradevicecolor2=#333333, #45a6cf, #810081 +extradevices=80, 81, 82 +extramathexpression1=, , +extramathexpression2=, , +extraname1=XT, {1}, TT +extraname2=Pa, {0}, RC + +[S7] +PID_OFF_action= +PID_ON_action= +PID_SV_register=0 +PID_area=0 +PID_d_register=0 +PID_db_nr=0 +PID_i_register=0 +PID_p_register=0 +PIDmultiplier=0 +SVmultiplier=0 +area=6, 6, 6, 6, 6, 6, 6, 6, 0, 0 +db_nr=84, 84, 84, 84, 84, 84, 1652, 84, 1, 1 +div=0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +host=192.168.1.10 +mode=1, 1, 1, 0, 0, 0, 1, 1, 0, 0 +port=102 +rack=0 +slot=1 +start=8, 4, 12, 44, 0, 20, 40, 36, 0, 0 +type=1, 1, 1, 1, 2, 2, 1, 2, 0, 0 +optimizer=true +fetch_max_blocks=true + +[events] +etypes=, , RC, , + +[Sliders] +eventsliderunits=%, %, , + +[Quantifiers] +clusterEventsFlag=false +eventquantifierSV=0, 0, 0, 0 +eventquantifieraction=0, 0, 0, 0 +quantifieractive=1, 1, 1, 0 +quantifiercoarse=0, 0, 0, 0 +quantifiermax=100, 100, 100, 100 +quantifiermin=0, 0, 0, 0 +quantifiersource=5, 4, 7, 0 \ No newline at end of file diff --git a/src/requirements-dev.txt b/src/requirements-dev.txt index 417e4b163..707fdfaa3 100644 --- a/src/requirements-dev.txt +++ b/src/requirements-dev.txt @@ -4,13 +4,13 @@ types-psutil==5.9.5.16 types-pyserial==3.5.0.10 types-python-dateutil==2.8.19.14 types-PyYAML==6.0.12.12 -types-requests==2.31.0.7 +types-requests==2.31.0.8 types-setuptools==68.2.0.0 types-urllib3==1.26.25.14 mypy==1.5.1 pyright==1.1.329 ruff>=0.0.285 -pylint==3.0.0 +pylint==3.0.1 pre-commit>=3.3.3 pytest==7.4.2 pytest-cov==4.1.0 @@ -21,6 +21,6 @@ pytest-qt==4.2.0 #pytest-bdd==6.1.1 #pytest-benchmark==4.0.0 #pytest-mock==3.11.1 -hypothesis==6.87.0 +hypothesis==6.87.2 coverage==7.3.2 coverage-badge==1.1.0 diff --git a/src/requirements.txt b/src/requirements.txt index a5932ed24..e1929bd9f 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -61,7 +61,7 @@ lxml==4.9.3 matplotlib==3.7.3; python_version < '3.9' # last Python 3.8 release matplotlib==3.8.0; python_version >= '3.9' jinja2==3.1.2 -aiohttp==3.8.5 +aiohttp==3.8.6 aiohttp_jinja2==1.5.1 # #