Ejemplo n.º 1
0
 def _convert_message(
         self, clresp: commlink.CLResponse) -> typing.Optional[CommonMSG]:
     """Convert an RFID response into a common message.
     Return None if this message should not be passed on.
     """
     # assume that we are going to return this message...
     ret_code: commlink.TLSRetCode = clresp.return_code()
     if ret_code == commlink.BaseCommLink.RC_TIMEOUT:
         return CommonMSG(CommonMSG.MSG_SV_RFID_STATREP,
                          CommonMSG.RFID_TIMEOUT)
     ret_is_ok = (ret_code == commlink.BaseCommLink.RC_OK)
     # A: determine the kind of message to return based on the comment_dict
     # or the current mode
     # Our decision is stored into msg_type
     msg_type = None
     ret_data: typing.Optional[typing.List[typing.Any]] = None
     comm_dct = clresp.get_comment_dct()
     if comm_dct is None:
         comment_str = None
     else:
         comment_str = comm_dct.get(commlink.BaseCommLink.COMMENT_ID, None)
         self._log_debug("clresp comment {}, Comment: {}".format(
             clresp, comment_str))
     if comment_str is None:
         # we have a message because the user pressed the trigger --
         # try to determine what kind of message to send back
         # based on our current mode
         if self.mode == TlsMode.radar:
             msg_type = CommonMSG.MSG_RF_RADAR_DATA
         elif self.mode == TlsMode.stock:
             msg_type = CommonMSG.MSG_RF_CMD_RESP
         else:
             self._log_debug('no comment_str and no mode: returning None')
             msg_type = None
     elif comment_str == 'radarsetup':
         # the server has previously sent a command to the RFID reader to go into
         # radar mode. We generate a message only if this failed.
         if not ret_is_ok:
             msg_type = CommonMSG.MSG_RF_CMD_RESP
     elif comment_str == 'RAD':
         msg_type = CommonMSG.MSG_RF_RADAR_DATA
     elif comment_str == 'IVreset':
         if not ret_is_ok:
             msg_type = CommonMSG.MSG_RF_CMD_RESP
     else:
         self._log_error('unhandled comment string {}'.format(comment_str))
     # B: now try to determine ret_data.
     if msg_type is None:
         return None
     if msg_type == CommonMSG.MSG_RF_RADAR_DATA:
         self.runningave.add_clresp(clresp)
         ret_data = self.runningave.get_runningave()
         self._log_debug("Returning radar data {}".format(ret_data))
     elif msg_type == CommonMSG.MSG_RF_CMD_RESP:
         ret_data = clresp.rl
     # do something with ret_data here and return a CommonMSG or None
     if ret_data is None:
         return None
     assert msg_type is not None and ret_data is not None, "convert_message error 99"
     return CommonMSG(msg_type, ret_data)
Ejemplo n.º 2
0
 def test_commonmsg01(self):
     """Check illegal msgtypes are caught."""
     mydat = 100.0
     # wrong type or value should raise an appropriate assertion
     for msg, exc in [([1, 2], TypeError), ("blastr", ValueError)]:
         with pytest.raises(exc):
             CommonMSG(msg, mydat)
Ejemplo n.º 3
0
    def generate_msg(self) -> typing.Optional[CommonMSG]:
        """Read a message from the RFID reader device if one is present.
        Convert this message into a CommonMsg instance or None and return it.
        The returned message will be put on the TaskMeister's queue.

        Typically, when the user presses the trigger of the RFID reader,
        we will send a message with the scanned data back.

        Note:
           This method overrules the method defined in BaseTaskMeister.
        """
        self._log_debug("TLS GM enter")
        # check for a change of the state of the commlink first.
        # if the state has changed, report this.
        new_state = self._cl.get_rfid_state()
        if new_state != self.cur_state:
            self.cur_state = new_state
            self._log_debug(
                "TLS: state change reported. new state: {}".format(new_state))
            return CommonMSG(CommonMSG.MSG_SV_RFID_STATREP, new_state)
        # no state change. if its up:
        #   read something (blocking) and return that (could be None)
        # else:
        #   return None the taskmeister will ignore it.
        if self.cur_state == CommonMSG.RFID_ON:
            self._log_debug("TLS before read... ")
            clresp: commlink.CLResponse = self._cl.raw_read_response()
            self._log_debug("TLS got {}".format(clresp))
            return self._convert_message(clresp)
        self._log_debug("TLS state is: {}, returning None".format(
            self.cur_state))
        return None
Ejemplo n.º 4
0
 def refresh_locmut_dct(self) -> None:
     """Request a new locmutation list from the stocky server
     if we need an update.
     This is done by sending a hash of the current data.
     The server will send an update if our data is out of date.
     """
     self.send_WS_msg(
         CommonMSG(CommonMSG.MSG_WC_LOCMUT_REQ, self.locmut_hash))
Ejemplo n.º 5
0
    def send_ws_msg(self, msg: CommonMSG) -> None:
        """Send a command to the web client over websocket in a standard JSON format.

        Args:
           msg: the message to send.
        """
        if self.ws is not None:
            self.ws.sendMSG(msg.as_dict())
Ejemplo n.º 6
0
 def generate_msg(self) -> typing.Optional[CommonMSG]:
     """
     Generate a message if the monitored file has appeared or disappeared
     since the last call.
     """
     newstate = self.file_exists()
     if self._curstate != newstate:
         self._curstate = newstate
         return CommonMSG(CommonMSG.MSG_SV_FILE_STATE_CHANGE, newstate)
     return None
Ejemplo n.º 7
0
 def test_delay01(self) -> None:
     """Perform test of a DelayTaskMeister"""
     tn = self.msgq.num_messages()
     if tn != 0:
         raise RuntimeError("unexpected tn = {}".format(tn))
     msg = CommonMSG(CommonMSG.MSG_SV_RAND_NUM, 'delaytest')
     d = Taskmeister.DelayTaskMeister(self.msgq, self.logger,
                                      self.sec_interval, msg)
     d.trigger()
     gevent.sleep(self.test_sleep_time)
     tn = self.msgq.num_messages()
     if tn != 1:
         raise RuntimeError("unexpected tn = {}".format(tn))
Ejemplo n.º 8
0
 def _init_rfid_server(self, CommLinkClass) -> None:
     """Perform initialisation activities for the RFID server.
     This server only talks to the RFID reader via rfcomm and serves
     the results via websockets.
     """
     # start the rfcomm daemon...
     # the command to run is something along the lines of:
     # "/usr/bin/rfcomm connect /dev/rfcomm0 88:6B:0F:86:4D:F9"
     rfcomm_cmd = "{} connect {} {} ".format(
         self.cfg_dct['RFCOMM_PROGRAM'],
         self.cfg_dct['RFID_READER_DEVNAME'],
         self.cfg_dct['RFID_READER_BT_ADDRESS'])
     self.logger.debug("rfcomm command : '{}'".format(rfcomm_cmd))
     self.rfcommtask = Taskmeister.DaemonTaskMeister(
         self.logger, rfcomm_cmd, 1)
     rfstat = self.rfcommtask.get_status()
     if rfstat != Taskmeister.DaemonTaskMeister.STATUS_RUNNING:
         self.logger.error(
             "rfcomm daemon is not running: status = {}".format(rfstat))
         raise RuntimeError("rfcomm program has not started")
     self.logger.debug("rfcomm comand is running.")
     self.logger.debug("serverclass: instantiating CommLinkClass...")
     self.filewatcher = Taskmeister.FileChecker(
         self.msgQ, self.logger, 5, True,
         self.cfg_dct['RFID_READER_DEVNAME'])
     self.comm_link = CommLinkClass(self.cfg_dct)
     if self.comm_link is None:
         self.logger.error("serverclass: comm_link is None!...")
         return
     self.logger.debug("serverclass: instantiating TLSAscii...")
     self.tls = TLSAscii.TLSReader(self.msgQ, self.logger, self.comm_link,
                                   AVENUM)
     # create messages and a delayTM for the RFID activity spinner
     self._rfid_act_on = CommonMSG(CommonMSG.MSG_SV_RFID_ACTIVITY, True)
     rfid_act_off = CommonMSG(CommonMSG.MSG_SV_RFID_ACTIVITY, False)
     # set up the RFID activity delay timer
     self.rfid_delay_task = Taskmeister.DelayTaskMeister(
         self.msgQ, self.logger, 1.5, rfid_act_off)
Ejemplo n.º 9
0
 def send_server_config(self) -> None:
     """Collect information about the server configuration and send this
     to the webclient.
     """
     # NOTE: the cfg_dct has keys we do not want to send to the webclient.
     dd = self.cfg_dct
     cfg_dct = {k: dd[k] for k in serverconfig.known_set}
     # extract information about the RFID reader if its online.
     rfid_info_dct = self.comm_link.get_info_dct(
     ) if self.comm_link is not None else None
     if rfid_info_dct is not None:
         for k, val in rfid_info_dct.items():
             cfg_dct[k] = val
     self.send_ws_msg(CommonMSG(CommonMSG.MSG_SV_SRV_CONFIG_DATA, cfg_dct))
Ejemplo n.º 10
0
 def test_commonmsg01(self) -> None:
     c = CommonMSG(CommonMSG.MSG_SV_RAND_NUM, 10)
     assert c.msg == CommonMSG.MSG_SV_RAND_NUM, "wrong msg"
     assert c.data == 10, "wrong data"
     ll = CommonMSG.valid_msg_lst
     assert ll, "msg_lst expected"
     print("lst is {}".format(ll))
     #
     # ll = CommonMSG.bla
     # print("lst is {}".format(ll))
     # assert ll, "ll is empty"
     dd = CommonMSG.valid_msg_dct
     assert dd, "msg_dct expected"
     print("dct is {}".format(dd))
Ejemplo n.º 11
0
    def test_send_rfid_msg(self):
        """Test behaviour of send_rfid_msg() with a number of valid/ invalid
        arguments. E.g. sending an instance other than a CommonMSG should
        raise an exception.
        """
        with pytest.raises(TypeError):
            self.tls.send_rfid_msg('bla')

        cm = CommonMSG(CommonMSG.MSG_WC_RADAR_MODE, False)
        self.tls.send_rfid_msg(cm)
        assert self.tls.mode == TLSAscii.TlsMode.stock

        cm = CommonMSG(CommonMSG.MSG_WC_RADAR_MODE, True)
        self.tls.send_rfid_msg(cm)
        assert self.tls.mode == TLSAscii.TlsMode.radar

        cm = CommonMSG(CommonMSG.MSG_SV_GENERIC_COMMAND, '.iv')
        self.tls.send_rfid_msg(cm)
        assert self.tls.mode == TLSAscii.TlsMode.stock

        cm = CommonMSG(CommonMSG.MSG_SV_RAND_NUM, 'bla')
        with pytest.raises(RuntimeError):
            self.tls.send_rfid_msg(cm)
Ejemplo n.º 12
0
 def generate_msg(self) -> typing.Optional[CommonMSG]:
     # generate either a barcode or RFID scan ?
     do_barcode = random.random() < 0.5
     if do_barcode:
         nselect = 1
         prelim = ['CS', '.bc,']
     else:
         # RFID scan
         nselect = random.randrange(len(self.taglst))
         prelim = ['CS', '.iv,']
     sel_tags = random.choices(self.taglst, k=nselect)
     scan_data = [prelim] + [['EP', tag] for tag in sel_tags] + [['OK', '']]
     print("returning: '{}'".format(scan_data))
     return CommonMSG(CommonMSG.MSG_RF_CMD_RESP, scan_data)
Ejemplo n.º 13
0
    def test_commonmsg00(self):
        """Sanity check the MSG names...
        and check we can instantiate all message types."""
        msglst = CommonMSG.valid_msg_lst
        msgdct = CommonMSG.valid_msg_dct
        # names must be unique
        assert len(msglst) == len(msgdct), "unexpected dct length"

        assert len(msglst) == CommonMSG.NUM_MSG, "inconsistent lst length"

        # names must allow assignment to exactly one source.
        mydat = 100.0
        for msgtype in msglst:
            c = CommonMSG(msgtype, mydat)
            assert isinstance(c, CommonMSG), "expected a CommonMSG"
            assert c.msg == msgtype, "wrong type"
            assert c.data == mydat, "wrong data"

            nn = sum([
                c.is_from_server(),
                c.is_from_webclient(),
                c.is_from_rfid_reader()
            ])
            assert nn == 1, "illegal name {}".format(msgtype)
Ejemplo n.º 14
0
 def generate_msg(self) -> typing.Optional[CommonMSG]:
     """Block until a data message is received from the webclient over websocket
     in JSON format.
     The resulting python data structure is analysed. If it is a valid message
     as defined in :mod:`webclient.commonmsg` , it is put on the queue as
     a CommonMSG instance.
     """
     lverb = True
     if lverb:
         print("WSGM: before rec msg")
     dct = self.ws.receiveMSG()
     if lverb:
         print("WSGM: received msg")
     # the return value is either None or a dict.
     if dct is None:
         self._log_error("received None over ws, returning None")
         retmsg = None
     elif isinstance(dct, dict):
         need_keys = frozenset(['msg', 'data'])
         got_keys = set(dct.keys())
         if need_keys <= got_keys:
             # now make sure we have a legal msg field
             try:
                 retmsg = CommonMSG(dct['msg'], dct['data'])
             except (ValueError, TypeError):
                 self._log_error("illegal msgtype= '{}'".format(dct['msg']))
                 retmsg = None
             xtra_keys = got_keys - need_keys
             if xtra_keys:
                 self._log_warning(
                     "unexpected extra dict keys, got '{}'".format(
                         got_keys))
         else:
             self._log_error("unknown keys in {}".format(got_keys))
             retmsg = None
     #
     if retmsg is not None and retmsg.msg == CommonMSG.MSG_WC_EOF:
         self._set_task_finished()
     mmm = "WebSocketReader.generate_msg returning commonmsg..."
     self._log_debug(mmm)
     print(mmm)
     return retmsg
Ejemplo n.º 15
0
 def rcvMsg(self, whofrom: base.base_obj, msgdesc: base.MSGdesc_Type,
            msgdat: typing.Optional[base.MSGdata_Type]) -> None:
     lverb = True
     if lverb:
         # print("{}.rcvMsg: {}: {} from {}".format(self._idstr, msgdesc, msgdat, whofrom._idstr))
         print("{}.rcvMsg: {} from {}".format(self._idstr, msgdesc,
                                              whofrom._idstr))
     if msgdesc == base.MSGD_BUTTON_CLICK:
         print("wcstatus GOT BUTTON CLICK msgdat={}".format(msgdat))
         if msgdat is None:
             print("msgdat is None")
             return
         cmd = msgdat.get("cmd", None)
         print("wcstatus GOT BUTTON CLICK CMD {}".format(cmd))
         if cmd == CMD_LOGOUT:
             # the logout button was pressed
             self.send_WS_msg(CommonMSG(CommonMSG.MSG_WC_LOGOUT_TRY, 1))
         elif cmd == CMD_TRY_RFID_SERVER:
             self._check_for_RFID_server()
         else:
             print('wcstatus: unrecognised cmd {}'.format(cmd))
             return
     elif msgdesc == base.MSGD_COMMS_ARE_UP:
         # this happens when the stocky server or RFID server websocket first comes online.
         # Use it for setting status and some initial data caching.
         print("COMMS ARE UP: {}".format(whofrom))
         if whofrom == self._server_ws:
             self.set_WS_state(True)
             self.refresh_locmut_dct()
         elif whofrom == self._rfid_ws:
             print("MSG FROM RFID server!!")
     elif msgdesc == base.MSGD_COMMS_ARE_DOWN:
         # this happens when the stocky server crashes, taking
         # the websocket connection with it
         print("COMMS ARE DOWN: {}".format(whofrom))
         if whofrom == self._server_ws:
             self.set_WS_state(False)
         elif whofrom == self._rfid_ws:
             self._rfid_ws = None
             self.set_RFID_state(RFID_OFF)
Ejemplo n.º 16
0
 def test_wsreader01(self):
     """The WebSocketReader must behave sensibly when it reads
     junk from the websocket, and also produce a message on good data.
     """
     rawws = DummyWebsocket(self.sec_interval, None)
     ws = ServerWebSocket.JSONWebSocket(rawws, self.logger)
     wsr = Taskmeister.WebSocketReader(self.msgq,
                                       self.logger,
                                       ws,
                                       sec_interval=1.0,
                                       do_activate=False)
     assert wsr is not None, "wsr is None!"
     ok_dct = {'msg': CommonMSG.MSG_SV_RAND_NUM, 'data': 'dolly'}
     extra_dct = {
         'msg': CommonMSG.MSG_SV_RAND_NUM,
         'data': 'dolly',
         'extra': 'message'
     }
     ok_msg = CommonMSG(ok_dct['msg'], ok_dct['data'])
     for faulty_data, doraw, exp_val in [({
             'bla': 'blu'
     }, True, None), ({
             'msg': 'hello'
     }, True, None), ([1, 2, 3], True, None), (b'[1, 2}', False, None),
                                         ({
                                             'msg': 'hello',
                                             'data': 'dolly'
                                         }, True, None),
                                         ([1, 2, 3], True, None),
                                         (extra_dct, True, ok_msg),
                                         (ok_dct, True, ok_msg)]:
         if doraw:
             rawws = DummyWebsocket(self.sec_interval, faulty_data)
         else:
             rawws = DummyWebsocket(self.sec_interval, None)
             rawws._set_json_val(faulty_data)
         ws = ServerWebSocket.JSONWebSocket(rawws, self.logger)
         wsr.ws = ws
         retmsg = wsr.generate_msg()
         print("after sleep exp: {}, got {}".format(exp_val, retmsg))
Ejemplo n.º 17
0
 def send_qai_status(self, upd_dct: typing.Optional[dict]):
     """Send status information about the server's connection status
     to the webclient.
     """
     if upd_dct is not None:
         did_dbreq = True
         dbreq_ok = upd_dct.get("ok", False)
         dbreq_msg = upd_dct.get("msg", "no message")
     else:
         did_dbreq = False
         dbreq_ok = True
         dbreq_msg = "NOTE: No update from QAI database performed."
     wc_stock_dct = self.stockdb.generate_webclient_stocklist()
     self.send_ws_msg(
         CommonMSG(
             CommonMSG.MSG_SV_STOCK_INFO_RESP,
             dict(db_stats=self.stockdb.get_db_stats(),
                  upd_time=self.stockdb.get_update_time(),
                  stock_dct=wc_stock_dct,
                  did_dbreq=did_dbreq,
                  dbreq_ok=dbreq_ok,
                  dbreq_msg=dbreq_msg)))
Ejemplo n.º 18
0
 def send_WS_msg(self, msg: CommonMSG) -> None:
     """Send a message to the server via websocket."""
     if self.is_WS_up():
         self._server_ws.send(msg.as_dict())
     else:
         print("SEND IS NOOOT HAPPENING")
Ejemplo n.º 19
0
 def generate_msg(self) -> typing.Optional[CommonMSG]:
     cmdstr = self.cmdlst[self.nmsg]
     self.nmsg = (self.nmsg + 1) % len(self.cmdlst)
     return CommonMSG(CommonMSG.MSG_SV_GENERIC_COMMAND,
                      cmdstr) if cmdstr else None
Ejemplo n.º 20
0
 def generate_msg(self) -> typing.Optional[CommonMSG]:
     return CommonMSG(CommonMSG.MSG_SV_TIMER_TICK, self.msgid)
Ejemplo n.º 21
0
 def generate_msg(self) -> typing.Optional[CommonMSG]:
     number = round(random.random() * 10, 3)
     self._log_debug("random: {}".format(number))
     return CommonMSG(CommonMSG.MSG_SV_RAND_NUM, number)
Ejemplo n.º 22
0
    def server_handle_msg(self, msg: CommonMSG) -> None:
        """Handle this message to me, the stocky server

        Args:
           msg: the message to handle.
        """
        # self.logger.debug("server handling msg...")
        print("server handling msg...{}".format(msg))
        print("server handling msg...")
        if msg.msg == CommonMSG.MSG_WC_RADAR_MODE:
            radar_on = msg.data
            self.logger.debug("RADAR mode...{}".format(radar_on))
            self.timer_tm.set_active(radar_on)
        elif msg.msg == CommonMSG.MSG_SV_TIMER_TICK:
            self.logger.debug("server received tick...")
            # print("MY logger is called '{}'".format(get_logger_name(self.logger)))
            if self.tls is not None and self.tls.is_in_radarmode():
                self.tls.radar_get()
        elif msg.msg == CommonMSG.MSG_WC_LOGIN_TRY:
            self.logger.debug("server received LOGIN request...")
            print("server received LOGIN request...")
            # try to log in and send back the response
            u_name = msg.data.get('username', None)
            p_word = msg.data.get('password', None)
            if u_name is None or p_word is None:
                self.logger.debug(
                    "server received a None with LOGIN request...")
            else:
                self.logger.debug("LOGIN request data OK...")
            print("trying login")
            login_resp = self.qaisession.login_try(u_name, p_word)
            print("got login resp")
            # self.sleep(3)
            if not isinstance(login_resp, dict):
                raise RuntimeError("fatal login try error")
            self.send_ws_msg(CommonMSG(CommonMSG.MSG_SV_LOGIN_RES, login_resp))
            # dict(ok=False, msg="User unknown", data=msg.data)))
        elif msg.msg == CommonMSG.MSG_WC_LOGOUT_TRY:
            # log out and send back response.
            self.qaisession.logout()
            log_state = self.qaisession.is_logged_in()
            self.send_ws_msg(
                CommonMSG(CommonMSG.MSG_SV_LOGOUT_RES,
                          dict(logstate=log_state)))
        elif msg.msg == CommonMSG.MSG_WC_STOCK_INFO_REQ:
            # request about chemstock information
            do_update = msg.data.get('do_update', False)
            print("chemstock 1 do_update={}".format(do_update))
            upd_dct: typing.Optional[dict] = None
            if do_update:
                upd_dct = self.stockdb.update_from_qai()
                print("update dct {}".format(upd_dct))
            print("chemstock 2..")
            self.send_qai_status(upd_dct)
            print("chemstock 3")
        elif msg.msg == CommonMSG.MSG_WC_ADD_STOCK_REQ:
            # get a string for adding RFID labels to QAI.
            dct = msg.data
            rfidstrlst = dct.get('rfids', None)
            locid = dct.get('location', None)
            new_stock = dct.get('newstock', False)
            qai_str = self.qaisession.generate_receive_url(
                locid, rfidstrlst, new_stock)
            self.send_ws_msg(
                CommonMSG(CommonMSG.MSG_SV_ADD_STOCK_RESP, qai_str))
        elif msg.msg == CommonMSG.MSG_SV_RFID_STATREP:
            # print("state change enter")
            self.handle_rfid_clstatechange(msg.data)
            # print("state change exit")
        elif msg.msg == CommonMSG.MSG_SV_FILE_STATE_CHANGE:
            # print("state change enter")
            self.handle_rfid_filestatechange(msg.data)
            # print("state change exit")
        elif msg.msg == CommonMSG.MSG_WC_LOCATION_INFO:
            # location change information: save to DB
            self.stockdb.add_loc_changes(msg.data['locid'], msg.data['locdat'])
        elif msg.msg == CommonMSG.MSG_WC_LOCMUT_REQ:
            client_hash = msg.data
            newhash, rdct = self.stockdb.get_loc_changes(client_hash)
            self.send_ws_msg(
                CommonMSG(CommonMSG.MSG_SV_LOCMUT_RESP,
                          dict(data=rdct, hash=newhash)))
        elif msg.msg == CommonMSG.MSG_WC_DO_LOCMUT_REQ:
            move_dct = msg.data['locmove']
            res = self.stockdb.perform_loc_changes(move_dct)
            self.send_ws_msg(
                CommonMSG(CommonMSG.MSG_SV_DO_LOCMUT_RESP, dict(data=res)))
            self.en_queue(
                CommonMSG(CommonMSG.MSG_WC_STOCK_INFO_REQ,
                          dict(do_update=True)))
            self.en_queue(
                CommonMSG(CommonMSG.MSG_WC_LOCMUT_REQ, dict(data=None)))
        else:
            self.logger.error("server not handling message {}".format(msg))
            raise RuntimeError("unhandled message {}".format(msg))
        # print("--END of server handling msg...{}".format(msg))
        print("--END of server handling msg...")
Ejemplo n.º 23
0
 def start_QAI_download(self):
     """Tell server to start download of QAI data..."""
     self.send_WS_msg(
         CommonMSG(CommonMSG.MSG_WC_STOCK_INFO_REQ, dict(do_update=True)))
Ejemplo n.º 24
0
 def rcvMsg(self, whofrom: base.base_obj, msgdesc: base.MSGdesc_Type,
            msgdat: typing.Optional[base.MSGdata_Type]) -> None:
     lverb = True
     if lverb:
         # print("{}.rcvMsg: {}: {} from {}".format(self._idstr, msgdesc, msgdat, whofrom._idstr))
         print("{}.rcvMsg: {} from {}".format(self._idstr, msgdesc,
                                              whofrom._idstr))
     if msgdesc == base.MSGD_SERVER_MSG:
         # message from the server.
         if msgdat is None:
             print("msgdat is None")
             return
         cmd = msgdat.get("msg", None)
         val = msgdat.get("data", None)
         if cmd == CommonMSG.MSG_SV_RFID_STATREP and self.wcstatus is not None:
             print("GOT RFID state {}".format(val))
             self.wcstatus.set_RFID_state(val)
             print("state set OK")
         elif cmd == CommonMSG.MSG_SV_RFID_ACTIVITY and self.wcstatus is not None:
             self.wcstatus.set_RFID_state(CommonMSG.RFID_ON)
             self.wcstatus.set_rfid_activity(val)
         elif cmd == CommonMSG.MSG_SV_RAND_NUM:
             # print("GOT number {}".format(val))
             newnum = val
             numlst = self.numlst
             while len(numlst) >= LST_NUM:
                 numlst.pop(0)
             numlst.append(newnum)
             # print("LEN {}".format(len(self.numlst)))
             # self.showlist()
         elif cmd == CommonMSG.MSG_RF_RADAR_DATA:
             self.setradardata(val)
         elif cmd == CommonMSG.MSG_RF_CMD_RESP:
             self.sndMsg(base.MSGD_RFID_CLICK, val)
         elif cmd == CommonMSG.MSG_SV_LOGIN_RES:
             self.set_login_status(val)
         elif cmd == CommonMSG.MSG_SV_LOGOUT_RES and self.wcstatus is not None:
             self.wcstatus.set_logout_status()
         elif cmd == CommonMSG.MSG_SV_STOCK_INFO_RESP:
             self.set_qai_update(val)
         elif cmd == CommonMSG.MSG_SV_ADD_STOCK_RESP:
             self.addnewstock(val)
         elif cmd == CommonMSG.MSG_SV_LOCMUT_RESP:
             rdct, newhash = val['data'], val['hash']
             self.set_locmut_update(rdct, newhash)
         elif cmd == CommonMSG.MSG_SV_SRV_CONFIG_DATA and self.wcstatus is not None:
             self.wcstatus.set_server_cfg_data(val)
         else:
             print("unrecognised server command {}".format(msgdat))
     elif msgdesc == base.MSGD_BUTTON_CLICK:
         print("webclient GOT BUTTON CLICK msgdat={}".format(msgdat))
         if msgdat is None:
             print("msgdat is None")
             return
         cmd = msgdat.get("cmd", None)
         print("webclient GOT BUTTON CLICK CMD {}".format(cmd))
         if cmd == "viewswitch":
             # the switch view does the actual switching on the web client,
             # but we have to tell the server what 'mode' we are in so that
             # it can control the RFID reader appropriately.
             target_view = msgdat.get('target', None)
             radar_on = target_view == RADAR_VIEW_NAME
             self.send_WS_msg(
                 CommonMSG(CommonMSG.MSG_WC_RADAR_MODE, radar_on))
             if target_view is None:
                 print("target_view is None")
                 return
             if target_view == CHECK_STOCK_VIEW_NAME:
                 self.send_WS_msg(
                     CommonMSG(CommonMSG.MSG_WC_RADAR_MODE, False))
             else:
                 print('unknown view target {}'.format(target_view))
         elif cmd == 'roomswitch':
             print("roomswitch not being handled")
             # there is no self.lb...
             # se_ndx, se_val = self.lb.get_selected()
             # print("showchecklist: got LOCKY VBAL '{}'  '{}'".format(se_ndx, se_val))
             # self.showchecklist(se_ndx)
         elif cmd == wcviews.AddNewStockView.GO_ADD_NEW_STOCK or\
                 cmd == wcviews.AddNewStockView.GO_ADD_NEW_RFIDTAG:
             # the GO button of add new stock was pressed:
             # get the selected RFID tags and request an add URL from the server.
             print("GOT addnewstock GO button!")
             vv = self.switch.getView(ADDSTOCK_VIEW_NAME)
             add_info_dct = vv.get_selection_dct()
             add_info_dct[
                 'newstock'] = cmd == wcviews.AddNewStockView.GO_ADD_NEW_STOCK
             if add_info_dct is not None:
                 self.send_WS_msg(
                     CommonMSG(CommonMSG.MSG_WC_ADD_STOCK_REQ,
                               add_info_dct))
         else:
             print('webclient: unrecognised cmd {}'.format(cmd))
             return
     elif msgdesc == base.MSGD_FORM_SUBMIT:
         # the login form has sent us a login request. pass this to the server
         # for verification
         print("webclient GOT FORM SUBMIT".format(msgdat))
         un = msgdat.get('username', None) if msgdat is not None else None
         pw = msgdat.get('password', None) if msgdat is not None else None
         dd = {'username': un, 'password': pw}
         self.send_WS_msg(CommonMSG(CommonMSG.MSG_WC_LOGIN_TRY, dd))
         print("OK: sent message")
     else:
         print("unhandled message {}".format(msgdesc))
Ejemplo n.º 25
0
    def mainloop(self):
        """This routine is entered into when the webclient has established a
        websocket connection to the server.
        Flask will call this routine with a newly established web socket when
        the webclient makes a connection via the websocket protocol.

        .. note::
           mainloop is reentrant: we enter here with a new websocket every time
           the webclient is started or restarted...

        The general strategy of the mainloop is to initialise all parties concerned,
        then enter an infinite loop in which messages are taken from the message queue.
        Some messages are either simply passed on to interested parties, while
        others are handled as requests by the server itself in
        :meth:`server_handle_msg` .
        """
        lverb = True
        is_rfid_scanner = (self.comm_link is not None)

        print("mainloop begin: is_rfid_server: {}".format(is_rfid_scanner))
        self.logger.info("mainloop begin")
        # start a random generator thread for testing....
        # self.randTM = Taskmeister.RandomGenerator(self.msgQ, self.logger)
        # self.randTM.set_active(True)

        if is_rfid_scanner:
            # send the RFID status to the webclient
            rfid_stat = self.comm_link.get_rfid_state()
            self.send_ws_msg(
                CommonMSG(CommonMSG.MSG_SV_RFID_STATREP, rfid_stat))
        else:
            # send the stocky server config data
            self.send_server_config()
            # send the QAI update status to the webclient
            self.send_qai_status(None)

        do_loop = True
        while do_loop:
            if lverb:
                print("YO: before get")
            msg: CommonMSG = self.msgQ.get()
            self.logger.debug("handling msgtype '{}'".format(msg.msg))
            if lverb:
                print("YO: handling msgtype '{}'".format(msg.msg))
            # handle a EOF separately
            if msg.msg == CommonMSG.MSG_WC_EOF:
                if lverb:
                    print("mainloop detected WS_EOF... quitting")
                self.ws = None
                do_loop = False
            print("step 2")
            if msg.is_from_rfid_reader():
                self.logger.debug("GOT RFID {}".format(msg.as_dict()))
                self.activate_rfid_spinner()

            is_handled = False
            if self.ws is not None and msg.msg in CommonStockyServer.MSG_FOR_WC_SET:
                is_handled = True
                # print("sending to WS...")
                self.send_ws_msg(msg)
                # print("...OK send")
            if self.tls is not None and msg.msg in CommonStockyServer.MSG_FOR_RFID_SET:
                is_handled = True
                self.tls.send_rfid_msg(msg)
            if msg.msg in CommonStockyServer.MSG_FOR_ME_SET:
                print("msg for me: {}".format(msg.msg))
                is_handled = True
                self.server_handle_msg(msg)
                print("done handling")
            if not is_handled:
                mmm = "mainloop DID NOT handle msgtype '{}'".format(msg.msg)
                self.logger.error(mmm)
                print(mmm)
            print("end of ML.while")
        print("OUT OF LOOP")