Exemple #1
0
static bool s_heart_hid_printer(ticket_printer_t *self) {
    if ((zclock_time() - self->hid_status_at) > 5000) {
#ifdef __WIN32__
        char *command = strdup("<S1>");
        int ret = boca_hid_write(self->hid_printer, command, strlen(command));
        free(command);
        enum BOCA_STATUS status = BOCA_OFFLINE;
        if (ret > 0) {
            zclock_sleep(500);
            status = boca_hid_status(self->hid_printer);
            self->event = EVENT_BOCA_WRITE_OK;
            s_state_machine(self);
        } else {
            self->event = EVENT_BOCA_WRITE_ERROR;
            s_state_machine(self);
            s_handle_boca_status(self, &status, true);
        }
#else
        enum BOCA_FEATURE_REPORT_STATUS feature_status = boca_hid_status_feature(self->hid_printer);
        enum BOCA_STATUS status = boca_status_from_feature(feature_status);
#endif
        s_handle_boca_status(self, &status, true);
        return true;
    }
    return false;
}
Exemple #2
0
static void s_restart_boca_serial(ticket_printer_t *self, const char *port) {
    boca_serial_destroy(&self->serial_printer);
    self->serial_printer = boca_serial_new(port);
    if (self->serial_printer == NULL) {
        zsys_warning("ticket printer: restart serial printer failed");
        self->event = EVENT_BOCA_ERROR_STATUS;
        s_state_machine(self);
    } else {
        zsys_info("ticket printer: restart serial printer ok.");
        self->event = EVENT_BOCA_RESTARTED;
        s_state_machine(self);
        self->boca_serial_restart_count = 0;
    }
}
Exemple #3
0
static void s_restart_boca_hid(ticket_printer_t *self, const char *dev_path) {
#ifdef __APPLE__
    //for mac we have to rescan to bring boca back.
    zstr_send(self->printer_store_req,"SCANPRINTERS");
    zstr_recv(self->printer_store_req);
#endif
    boca_hid_destroy(&self->hid_printer);
    self->hid_printer = boca_hid_new(dev_path);
    if (self->hid_printer == NULL) {
        zsys_warning("ticket printer: restart hid printer failed");
        self->event = EVENT_BOCA_ERROR_STATUS;
        s_state_machine(self);
    } else {
        zsys_warning("ticket printer: restart hid printer ok");
        self->event = EVENT_BOCA_RESTARTED;
        s_state_machine(self);
        self->boca_hid_restart_count = 0;
    }
}
Exemple #4
0
static int reader_pipe_event(zloop_t *loop, zsock_t *reader, void *arg) {
    int ret = 0;
    ticket_printer_t *self = (ticket_printer_t *) arg;
    zmsg_t *request = zmsg_recv(self->pipe);
    if (!request) {
        return -1;
    }
    char *command = zmsg_popstr(request);
    if (self->verbose) {
        zsys_debug("ticket printer: API command %s", command);
    }
    if (streq(command, "$TERM")) {
        self->event = EVENT_TERM;
        s_state_machine(self);
        ret = -1;
    } else if (streq(command, "VERBOSE")) {
        self->verbose = true;
        if (self->hid_printer != NULL)
            boca_hid_set_verbose(self->hid_printer, self->verbose);
#ifdef __WIN32__
        if (self->serial_printer != NULL)
            boca_serial_set_verbose(self->serial_printer, self->verbose);
#endif
    } else if (streq(command, "START")) {
        char *ticket_store_endpoint = zmsg_popstr(request);
        self->ticket_store_req = zsock_new_req(ticket_store_endpoint);
        zsys_info("ticket printer: ticket printer is using ticket store %s", ticket_store_endpoint);
        zstr_free(&ticket_store_endpoint);
        self->event = EVENT_TICKET_STORE_READY;
        s_state_machine(self);
        zsock_signal(self->pipe, 0);
    } else if (streq(command, "SETPRINTERSTORE")) {
        char *printer_store_ep = zmsg_popstr(request);
        self->printer_store_req = zsock_new_req(printer_store_ep);
        zstr_free(&printer_store_ep);
        zsock_signal(self->pipe, 0);
    } else if (streq(command, "SETDIAGNOSTIC")) {
        self->diagnostic = true;
    }
    zstr_free(&command);
    zmsg_destroy(&request);
    return ret;
}
Exemple #5
0
int main (int argc, char *argv [])
{
    //  Arguments can be either of:
    //      -p  primary server, at tcp://localhost:5001
    //      -b  backup server, at tcp://localhost:5002
    zctx_t *ctx = zctx_new ();
    void *statepub = zsocket_new (ctx, ZMQ_PUB);
    void *statesub = zsocket_new (ctx, ZMQ_SUB);
    zsockopt_set_subscribe (statesub, "");
    void *frontend = zsocket_new (ctx, ZMQ_ROUTER);
    bstar_t fsm = { 0 };

    if (argc == 2 && streq (argv [1], "-p")) {
        printf ("I: Primary master, waiting for backup (slave)\n");
        zsocket_bind (frontend, "tcp://*:5001");
        zsocket_bind (statepub, "tcp://*:5003");
        zsocket_connect (statesub, "tcp://localhost:5004");
        fsm.state = STATE_PRIMARY;
    }
    else
    if (argc == 2 && streq (argv [1], "-b")) {
        printf ("I: Backup slave, waiting for primary (master)\n");
        zsocket_bind (frontend, "tcp://*:5002");
        zsocket_bind (statepub, "tcp://*:5004");
        zsocket_connect (statesub, "tcp://localhost:5003");
        fsm.state = STATE_BACKUP;
    }
    else {
        printf ("Usage: bstarsrv { -p | -b }\n");
        zctx_destroy (&ctx);
        exit (0);
    }
    //  Set timer for next outgoing state message
    int64_t send_state_at = zclock_time () + HEARTBEAT;

    while (!zctx_interrupted) {
        zmq_pollitem_t items [] = {
            { frontend, 0, ZMQ_POLLIN, 0 },
            { statesub, 0, ZMQ_POLLIN, 0 }
        };
        int time_left = (int) ((send_state_at - zclock_time ()));
        if (time_left < 0)
            time_left = 0;
        int rc = zmq_poll (items, 2, time_left * ZMQ_POLL_MSEC);
        if (rc == -1)
            break;              //  Context has been shut down

        if (items [0].revents & ZMQ_POLLIN) {
            //  Have a client request
            zmsg_t *msg = zmsg_recv (frontend);
            fsm.event = CLIENT_REQUEST;
            if (s_state_machine (&fsm) == FALSE)
                //  Answer client by echoing request back
                zmsg_send (&msg, frontend);
            else
                zmsg_destroy (&msg);
        }
        if (items [1].revents & ZMQ_POLLIN) {
            //  Have state from our peer, execute as event
            char *message = zstr_recv (statesub);
            fsm.event = atoi (message);
            free (message);
            if (s_state_machine (&fsm))
                break;          //  Error, so exit
            fsm.peer_expiry = zclock_time () + 2 * HEARTBEAT;
        }
        //  If we timed-out, send state to peer
        if (zclock_time () >= send_state_at) {
            char message [2];
            sprintf (message, "%d", fsm.state);
            zstr_send (statepub, message);
            send_state_at = zclock_time () + HEARTBEAT;
        }
    }
    if (zctx_interrupted)
        printf ("W: interrupted\n");

    //  Shutdown sockets and context
    zctx_destroy (&ctx);
    return 0;
}
Exemple #6
0
static void s_print_tix(ticket_printer_t *self, bool serial) {
#ifdef __WIN32__ 
    if (serial && self->serial_printer == NULL) return;
#endif
    if (!serial && self->hid_printer == NULL) return;
    bool is_stop = false;
    int queue_size = serial ? TICKET_PRINTING_SIZE_SERIAL : TICKET_PRINTING_SIZE;
    while (self->tix_counter < queue_size && !is_stop) {
        int bytes_written = 0;
        char count_str[15];
        sprintf(count_str, "%d", queue_size - self->tix_counter);
        zstr_sendx(self->ticket_store_req, "GETNEXTTICKETS", self->last_token, count_str, NULL);
        zpoller_t *poller = zpoller_new(self->ticket_store_req, NULL);
        zsock_t *reader = zpoller_wait(poller, 800);
        if (reader == NULL) {
            is_stop = true;
        } else {
            zmsg_t *msg = zmsg_recv(self->ticket_store_req);
            char *result = zmsg_popstr(msg);

            if (streq(result, "OK")) {
                char *count_str_resp = zmsg_popstr(msg);
                int tix_count = atoi(count_str_resp);
                zsys_info("ticket printer: read %d tix back", tix_count);
                while (tix_count > 0) {
                    char *group = zmsg_popstr(msg);
                    char *token = zmsg_popstr(msg);
                    char *data = zmsg_popstr(msg);
                    char *seq = zmsg_popstr(msg);
                    zsys_info("ticket printer: sending tix %s to BOCA", seq);
                    if (self->diagnostic) {
                        char diagnostic_fgl[100] = {'\0'};
                        sprintf(diagnostic_fgl, "<RR><RC25,1050><F2>S_%s", seq);
#ifdef __WIN32__                        
                        serial ? boca_serial_write(self->serial_printer, diagnostic_fgl) : boca_hid_write(
                                self->hid_printer,
                                diagnostic_fgl,
                                strlen(diagnostic_fgl));
#else
                        boca_hid_write(
                                self->hid_printer,
                                diagnostic_fgl,
                                strlen(diagnostic_fgl));
#endif
                    }
#ifdef __WIN32__
                    bytes_written = serial ? boca_serial_write(self->serial_printer, data) : boca_hid_write(
                            self->hid_printer,
                            data, strlen(data));
#else
                    bytes_written = boca_hid_write(
                            self->hid_printer,
                            data, strlen(data));
#endif
                    if (bytes_written > 0) {
                        self->tix_counter++;
                        self->event = EVENT_BOCA_WRITE_OK;
                        s_state_machine(self);
                    } else {
                        zsys_warning("ticket printer: can not write fgl to hid printer");
                        self->event = EVENT_BOCA_WRITE_ERROR;
                        s_state_machine(self);
                        is_stop = true;
                    }
                    free(self->last_token);
                    self->last_token = strdup(token);
                    zstr_free(&group);
                    zstr_free(&token);
                    zstr_free(&data);
                    zstr_free(&seq);
                    tix_count--;
                }
                zstr_free(&count_str_resp);
            } else {
                is_stop = true;
            }
            zstr_free(&result);
            zmsg_destroy(&msg);
        }
        zpoller_destroy(&poller);
    }
}
Exemple #7
0
static void s_handle_boca_status(ticket_printer_t *self, enum BOCA_STATUS *status, bool is_hid) {
    switch ((*status)) {
        case BOCA_TICKET_ACK:
            zstr_send(self->ticket_store_req, "TICKETPRINTED");
            char *code = zstr_recv(self->ticket_store_req);
            if (code != NULL && streq(code, "OK")) {
                self->tix_counter--;
            }
            if (code != NULL) zstr_free(&code);
            self->event = EVENT_BOCA_ACK;
            s_state_machine(self);
            break;
        case BOCA_INVALID_CHECKSUM:
            self->event = EVENT_BOCA_ERROR_STATUS;
            s_state_machine(self);
            break;
        case BOCA_OUT_OF_PAPER:
            self->event = EVENT_BOCA_OOP;
            s_state_machine(self);
            break;
        case BOCA_X_ON:
            self->event = EVENT_BOCA_READY;
            s_state_machine(self);
            break;
        case BOCA_POWER_ON:
            self->state = STATE_IDLE;
            break;
        case BOCA_X_OFF:
            self->event = EVENT_BOCA_BUSY;
            s_state_machine(self);
            break;
        case BOCA_NAK:
            self->event = EVENT_BOCA_ERROR_STATUS;
            s_state_machine(self);
            break;
        case BOCA_PAPER_JAM:
            self->event = EVENT_BOCA_ERROR_STATUS;
            s_state_machine(self);
            break;
        case BOCA_ILLEGAL_DATA:
            self->event = EVENT_BOCA_ERROR_STATUS;
            s_state_machine(self);
            break;
        case BOCA_POWERUP_PROBLEM:
            self->event = EVENT_BOCA_ERROR_STATUS;
            s_state_machine(self);
            break;
        case BOCA_DOWNLOADING_ERROR:
            self->event = EVENT_BOCA_ERROR_STATUS;
            s_state_machine(self);
            break;
        case BOCA_CUTTER_JAM:
            self->event = EVENT_BOCA_ERROR_STATUS;
            s_state_machine(self);
            break;
        case BOCA_STUCK_TICKET:
            self->event = EVENT_BOCA_ERROR_STATUS;
            s_state_machine(self);
            break;
        case BOCA_UNKNOWN:
            break;
        case BOCA_OFFLINE:
            self->event = EVENT_BOCA_ERROR_STATUS;
            s_state_machine(self);
            break;
        case BOCA_GENERAL_ERROR:
            self->event = EVENT_BOCA_ERROR_STATUS;
            s_state_machine(self);
            break;
    }
    if (self->printer_store_req != NULL && (*status) != BOCA_UNKNOWN) {
        char str_status[5];
        sprintf(str_status, "%d", boca_status_to_int((*status)));
        if (is_hid) {
            zstr_sendx(self->printer_store_req, "SETHIDPRINTERSTATUS", self->boca_hid_device_path, str_status,
                       NULL);
            zmsg_t *resp = zmsg_recv(self->printer_store_req);
            char *result = zmsg_popstr(resp);
            if (streq(result, "FAIL")) {
                zsys_warning("ticket printer: could not update hid printer %s status %s",
                             self->boca_hid_device_path,
                             boca_status_display((*status)));
            } else {
                self->hid_status_at = zclock_time();
            }
            zmsg_destroy(&resp);
        }
#ifdef __WIN32__
        else {
            zstr_sendx(self->printer_store_req, "SETSERIALPRINTERSTATUS", self->serial_printer->port, str_status, NULL);
            zmsg_t *resp = zmsg_recv(self->printer_store_req);
            char *result = zmsg_popstr(resp);
            if (streq(result, "FAIL")) {
                zsys_warning("ticket printer: could not update serial printer %s status %s", self->serial_printer->port,
                             boca_status_display((*status)));
            } else {
                if (self->verbose)
                    zsys_debug("ticket printer: update serial printer %s status %s", self->serial_printer->port,
                               boca_status_display((*status)));
                self->serial_status_at = zclock_time();
            }
            zmsg_destroy(&resp);
        }
#endif
    }
}