Skip to content

Commit

Permalink
- removes MODBUS serial parameter 'strict'
Browse files Browse the repository at this point in the history
- prevents assignment of roasts to completed schedule items
- prevents sending multiple LockSchedule message for one account/date
- prevents zero aspect ratio in Cup Profile
- updates SCI setups
  • Loading branch information
MAKOMO committed Oct 2, 2024
1 parent 7af38be commit 427e565
Show file tree
Hide file tree
Showing 85 changed files with 35,452 additions and 35,404 deletions.
14 changes: 9 additions & 5 deletions src/artisanlib/async_comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ async def handle_writes(self, writer: asyncio.StreamWriter, queue: 'asyncio.Queu
await writer.drain()

# if serial settings are given, host/port are ignore and communication is handled by the given serial port
async def connect(self) -> None:
async def connect(self, connect_timeout:float=2) -> None:
writer = None
while True:
try:
Expand All @@ -197,7 +197,7 @@ async def connect(self) -> None:
_log.debug('connecting to %s:%s ...', self._host, self._port)
connect = asyncio.open_connection(self._host, self._port)
# Wait for 2 seconds, then raise TimeoutError
reader, writer = await asyncio.wait_for(connect, timeout=2)
reader, writer = await asyncio.wait_for(connect, timeout=connect_timeout)
_log.debug('connected')
if self._connected_handler is not None:
try:
Expand Down Expand Up @@ -235,18 +235,22 @@ async def connect(self) -> None:
except Exception as e: # pylint: disable=broad-except
_log.exception(e)

await asyncio.sleep(1)
await asyncio.sleep(0.7)

def send(self, message:bytes) -> None:
if self.async_loop_thread is not None and self._write_queue is not None:
asyncio.run_coroutine_threadsafe(self._write_queue.put(message), self.async_loop_thread.loop)


# start/stop sample thread

def start(self) -> None:
def start(self, connect_timeout:float=2) -> None:
try:
_log.debug('start sampling')
if self._asyncLoopThread is None:
self._asyncLoopThread = AsyncLoopThread()
# run sample task in async loop
asyncio.run_coroutine_threadsafe(self.connect(), self._asyncLoopThread.loop)
asyncio.run_coroutine_threadsafe(self.connect(connect_timeout), self._asyncLoopThread.loop)
except Exception as e: # pylint: disable=broad-except
_log.exception(e)

Expand Down
19 changes: 18 additions & 1 deletion src/artisanlib/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import platform
import math
import warnings
import datetime
import numpy
import logging
import re
Expand Down Expand Up @@ -1476,6 +1477,10 @@ def __init__(self, parent:QWidget, dpi:int, locale:str, aw:'ApplicationWindow')
# plus_file_last_modified is set on load, reset on RESET, and updated on save. It is also update, if not None and new data is received from the server (sync:applyServerUpdates)
# this timestamp is used in sync:fetchServerUpdate to ask server for updated data

# remember the lockSchedule date/account sent to the server to prevent re-sending
self.plus_lockSchedule_sent_account:Optional[str] = None
self.plus_lockSchedule_sent_date:Optional[str] = None

self.beans:str = ''

self.curveVisibilityCache:Optional[Tuple[bool,bool,bool,bool,List[bool],List[bool]]] = None # caches the users curve visibility settings to be reset after recording
Expand Down Expand Up @@ -6611,6 +6616,10 @@ def reset(self,redraw:bool = True, soundOn:bool = True, keepProperties:bool = Fa
self.roastbatchpos = 1 # initialized to 1, set to increased batchsequence on DROP
self.roastbatchprefix = self.batchprefix

# reset scheduleID/Date (prevents re-using a previous loaded profiles scheduleID to be 'reused')
self.scheduleID = None
self.scheduleDate = None

self.aw.sendmessage(QApplication.translate('Message','Scope has been reset'))
self.aw.AUClcd.setNumDigits(3)
self.aw.buttonFCs.setDisabled(False)
Expand Down Expand Up @@ -12608,6 +12617,14 @@ def fireChargeTimer(self) -> None:
self.profileDataSemaphore.release(1)
self.markChargeSignal.emit(False) # this queues an event which forces a realignment/redraw by resetting the cache ax_background and fires the CHARGE action

def registerLockScheduleSent(self) -> None:
self.plus_lockSchedule_sent_account = self.aw.plus_account
self.plus_lockSchedule_sent_date = str(datetime.datetime.now().astimezone().date())

# returns True if the lockSchedule was already sent for today and the current account
def lockScheduleSent(self) -> bool:
return (self.plus_lockSchedule_sent_account is not None and self.plus_lockSchedule_sent_account == self.aw.plus_account and
self.plus_lockSchedule_sent_date is not None and self.plus_lockSchedule_sent_date == str(datetime.datetime.now().astimezone().date()))

def OnRecorder(self) -> None:
try:
Expand Down Expand Up @@ -12702,7 +12719,7 @@ def OnRecorder(self) -> None:
self.aw.update_minieventline_visibility()

# lock todays schedule
if self.aw.plus_account is not None and self.aw.schedule_window is not None:
if self.aw.plus_account is not None and self.aw.schedule_window is not None and len(self.aw.schedule_window.scheduled_items)>0 and not self.lockScheduleSent():
try:
sendLockSchedule()
except Exception: # pylint: disable=broad-except
Expand Down
2 changes: 1 addition & 1 deletion src/artisanlib/colortrack.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def register_reading(self, value:float) -> None:
_log.info('register_reading: %s',value)


# asyncio loop
# asyncio read implementation

# https://www.oreilly.com/library/view/using-asyncio-in/9781492075325/ch04.html
async def read_msg(self, stream: asyncio.StreamReader) -> None:
Expand Down
2 changes: 1 addition & 1 deletion src/artisanlib/cup_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def __init__(self, parent:'QWidget', aw:'ApplicationWindow') -> None:
aspectlabel = QLabel(QApplication.translate('Label','Aspect Ratio'))
self.aspectSpinBox = QDoubleSpinBox()
self.aspectSpinBox.setToolTip(QApplication.translate('Tooltip','Aspect Ratio'))
self.aspectSpinBox.setRange(0.,2.)
self.aspectSpinBox.setRange(0.5,2.)
self.aspectSpinBox.setSingleStep(.1)
self.aspectSpinBox.setValue(self.aw.qmc.flavoraspect)
self.aspectSpinBox.valueChanged.connect(self.setaspect)
Expand Down
9 changes: 4 additions & 5 deletions src/artisanlib/hottop.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ def valid_message(self, message:bytearray) -> bool:
self.HEADER[0:2] == message[0:2] and
(not self._verify_crc or int(message[35]) == sum(int(c) for c in message[:35]) & 0xFF))


# asyncio read implementation

# https://www.oreilly.com/library/view/using-asyncio-in/9781492075325/ch04.html
async def read_msg(self, stream: asyncio.StreamReader) -> None:
# look for the first header byte
Expand Down Expand Up @@ -156,11 +159,7 @@ def create_msg(self) -> bytes:
return bytes(cmd)

def send_control(self) -> None:
if self.async_loop_thread is not None:
msg = self.create_msg()
if self._write_queue is not None:
asyncio.run_coroutine_threadsafe(self._write_queue.put(msg), self.async_loop_thread.loop)

self.send(self.create_msg())

# External Interface

Expand Down
5 changes: 1 addition & 4 deletions src/artisanlib/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14787,7 +14787,7 @@ def setProfile(self, filename:Optional[str], profile:'ProfileData', quiet:bool =
if 'flavorstartangle' in profile:
self.qmc.flavorstartangle = int(profile['flavorstartangle'])
if 'flavoraspect' in profile:
self.qmc.flavoraspect = float(profile['flavoraspect'])
self.qmc.flavoraspect = min(2,max(0.5, float(profile['flavoraspect'])))
else:
self.qmc.flavoraspect = 1.
if 'title' in profile:
Expand Down Expand Up @@ -17117,7 +17117,6 @@ def settingsLoad(self, filename:Optional[str] = None, theme:bool = False, machin
self.modbus.stopbits = toInt(settings.value('stopbits',self.modbus.stopbits))
self.modbus.parity = s2a(toString(settings.value('parity',self.modbus.parity)))
self.modbus.timeout = max(0.3, float2float(toFloat(settings.value('timeout',self.modbus.timeout)))) # min serial MODBUS timeout is 300ms
self.modbus.serial_strict_timing = bool(toBool(settings.value('serial_strict_timing',self.modbus.serial_strict_timing)))
self.modbus.modbus_serial_connect_delay = toFloat(settings.value('modbus_serial_connect_delay',self.modbus.modbus_serial_connect_delay))
self.modbus.serial_readRetries = toInt(settings.value('serial_readRetries',self.modbus.serial_readRetries))
self.modbus.IP_timeout = float2float(toFloat(settings.value('IP_timeout',self.modbus.IP_timeout)))
Expand Down Expand Up @@ -18843,7 +18842,6 @@ def saveAllSettings(self, settings:QSettings, default_settings:Optional[Dict[str
self.settingsSetValue(settings, default_settings, 'stopbits',self.modbus.stopbits, read_defaults)
self.settingsSetValue(settings, default_settings, 'parity',self.modbus.parity, read_defaults)
self.settingsSetValue(settings, default_settings, 'timeout',self.modbus.timeout, read_defaults)
self.settingsSetValue(settings, default_settings, 'serial_strict_timing',self.modbus.serial_strict_timing, read_defaults)
self.settingsSetValue(settings, default_settings, 'modbus_serial_connect_delay',self.modbus.modbus_serial_connect_delay, read_defaults)
self.settingsSetValue(settings, default_settings, 'serial_readRetries',self.modbus.serial_readRetries, read_defaults)
self.settingsSetValue(settings, default_settings, 'IP_timeout',self.modbus.IP_timeout, read_defaults)
Expand Down Expand Up @@ -22831,7 +22829,6 @@ def setcommport(self, _:bool = False) -> None:
except Exception: # pylint: disable=broad-except
pass
try:
self.modbus.serial_strict_timing = bool(dialog.modbus_Serial_strict.isChecked())
self.modbus.IP_retries = dialog.modbus_IP_retriesComboBox.currentIndex()
self.modbus.PID_slave_ID = toInt(str(dialog.modbus_PIDslave_Edit.text()))
self.modbus.PID_SV_register = toInt(str(dialog.modbus_SVregister_Edit.text()))
Expand Down
60 changes: 0 additions & 60 deletions src/artisanlib/modbus_nonstrict_serial.py

This file was deleted.

4 changes: 2 additions & 2 deletions src/artisanlib/modbusport.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def getBinaryPayloadDecoderFromRegisters(registers:List[int], byteorderLittle:bo
class modbusport:
""" this class handles the communications with all the modbus devices"""

__slots__ = [ 'aw', 'modbus_serial_read_delay', 'modbus_serial_connect_delay', 'modbus_serial_write_delay', 'maxCount', 'readRetries', 'serial_strict_timing', 'default_comport', 'comport', 'baudrate', 'bytesize', 'parity', 'stopbits',
__slots__ = [ 'aw', 'modbus_serial_read_delay', 'modbus_serial_connect_delay', 'modbus_serial_write_delay', 'maxCount', 'readRetries', 'default_comport', 'comport', 'baudrate', 'bytesize', 'parity', 'stopbits',
'timeout', 'IP_timeout', 'IP_retries', 'serial_readRetries', 'PID_slave_ID', 'PID_SV_register', 'PID_p_register', 'PID_i_register', 'PID_d_register', 'PID_ON_action', 'PID_OFF_action',
'channels', 'inputSlaves', 'inputRegisters', 'inputFloats', 'inputBCDs', 'inputFloatsAsInt', 'inputBCDsAsInt', 'inputSigned', 'inputCodes', 'inputDivs',
'inputModes', 'optimizer', 'fetch_max_blocks', 'fail_on_cache_miss', 'disconnect_on_error', 'acceptable_errors', 'activeRegisters', 'readingsCache', 'SVmultiplier', 'PIDmultiplier',
Expand All @@ -126,7 +126,6 @@ def __init__(self, aw:'ApplicationWindow') -> None:
self.stopbits:int = 1
self.timeout:float = 0.4 # serial MODBUS timeout
self.serial_readRetries:int = 1 # user configurable, defaults to 0
self.serial_strict_timing:bool = False
self.IP_timeout:float = 0.2 # UDP/TCP MODBUS timeout in seconds
self.IP_retries:int = 1 # UDP/TCP MODBUS retries (max 3)
self.PID_slave_ID:int = 0
Expand Down Expand Up @@ -987,6 +986,7 @@ def readInt32(self, slave:int, register:int, code:int = 3,force:bool = False, si
tx = time.time()
error_disconnect:bool = False # set to True if a serious error requiring a disconnect was detected
res:Optional[int] = None

try:
res_registers:Optional[List[int]]
res_error_disconnect:bool
Expand Down
2 changes: 2 additions & 0 deletions src/artisanlib/mugma.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ def resetReadings(self) -> None:
self._sv = -1


# asyncio read implementation

# https://www.oreilly.com/library/view/using-asyncio-in/9781492075325/ch04.html
async def read_msg(self, stream: asyncio.StreamReader) -> None:
# read line
Expand Down
7 changes: 0 additions & 7 deletions src/artisanlib/ports.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,18 +705,11 @@ def __init__(self, parent:'QWidget', aw:'ApplicationWindow') -> None:
self.modbus_Serial_retriesComboBox.addItems([str(n) for n in range(4)])
self.modbus_Serial_retriesComboBox.setCurrentIndex(self.aw.modbus.serial_readRetries)

modbus_Serial_strict_label = QLabel(QApplication.translate('Label', 'Strict'))
self.modbus_Serial_strict = QCheckBox()
self.modbus_Serial_strict.setChecked(self.aw.modbus.serial_strict_timing)
self.modbus_Serial_strict.setFocusPolicy(Qt.FocusPolicy.NoFocus)

modbus_Serial_grid = QGridLayout()
modbus_Serial_grid.addWidget(modbus_Serial_delaylabel,0,0,Qt.AlignmentFlag.AlignRight)
modbus_Serial_grid.addWidget(self.modbus_Serial_delayEdit,0,1,Qt.AlignmentFlag.AlignRight)
modbus_Serial_grid.addWidget(modbus_Serial_retries,1,0,Qt.AlignmentFlag.AlignRight)
modbus_Serial_grid.addWidget(self.modbus_Serial_retriesComboBox,1,1,Qt.AlignmentFlag.AlignRight)
modbus_Serial_grid.addWidget(modbus_Serial_strict_label,2,0,Qt.AlignmentFlag.AlignRight)
modbus_Serial_grid.addWidget(self.modbus_Serial_strict,2,1,Qt.AlignmentFlag.AlignLeft)

modbus_Serial_layout = QVBoxLayout()
modbus_Serial_layout.addLayout(modbus_Serial_grid)
Expand Down
8 changes: 2 additions & 6 deletions src/artisanlib/santoker.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def register_reading(self, target:bytes, value:int) -> None:
_log.debug('unknown data target %s', target)


# asyncio loop
# asyncio read implementation

# https://www.oreilly.com/library/view/using-asyncio-in/9781492075325/ch04.html
async def read_msg(self, stream: asyncio.StreamReader) -> None:
Expand Down Expand Up @@ -210,11 +210,7 @@ def create_msg(self, target:bytes, value: int) -> bytes:
return self.HEADER + target + data + crc + self.TAIL

def send_msg(self, target:bytes, value: int) -> None:
if self.async_loop_thread is not None:
msg = self.create_msg(target, value)
if self._write_queue is not None:
asyncio.run_coroutine_threadsafe(self._write_queue.put(msg), self.async_loop_thread.loop)

self.send(self.create_msg(target, value))


def main() -> None:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[General]
Delay=2000
roastertype_setup=Sweet Coffee Italia – Gema 26-30IND
roastertype_setup=Sweet Coffee Italia – Gemma 26-30IND
roastersize_setup=30
roasterheating_setup=3

Expand Down Expand Up @@ -48,7 +48,7 @@ baudrate=115200
bytesize=8
comport=COM5
fetch_max_blocks=false
host=127.0.0.1
host=192.168.103.200
input10BCDsAsInt=false
input10FloatsAsInt=false
input10Signed=false
Expand All @@ -60,42 +60,42 @@ input10mode=C
input10register=0
input10slave=0
input1BCDsAsInt=false
input1FloatsAsInt=false
input1Signed=false
input1FloatsAsInt=true
input1Signed=true
input1bcd=false
input1code=3
input1div=0
input1float=true
input1div=1
input1float=false
input1mode=C
input1register=5004
input1slave=1
input2BCDsAsInt=false
input2FloatsAsInt=false
input2Signed=false
input2FloatsAsInt=true
input2Signed=true
input2bcd=false
input2code=3
input2div=0
input2float=true
input2div=1
input2float=false
input2mode=C
input2register=5000
input2slave=1
input3BCDsAsInt=false
input3FloatsAsInt=false
input3Signed=false
input3FloatsAsInt=true
input3Signed=true
input3bcd=false
input3code=3
input3div=0
input3float=true
input3div=1
input3float=false
input3mode=C
input3register=5006
input3slave=1
input4BCDsAsInt=false
input4FloatsAsInt=false
input4Signed=false
input4FloatsAsInt=true
input4Signed=true
input4bcd=false
input4code=3
input4div=0
input4float=true
input4div=1
input4float=false
input4mode=C
input4register=5002
input4slave=1
Expand Down Expand Up @@ -151,7 +151,7 @@ input9register=0
input9slave=0
littleEndianFloats=false
modbus_serial_connect_delay=0
optimizer=false
optimizer=true
parity=N
port=502
serial_readRetries=1
Expand Down
Loading

0 comments on commit 427e565

Please sign in to comment.