Example #1
0
ot_int sub_parse_request(m2session* session) {
    ot_int  score   = 0;
    ot_u8   cmd_opcode;
    //ot_u8   nack    = 0;

    /// 1.  Universal Comm Processing                                       <BR>
    ///     - Load CCA type & CSMA disable from command extension           <BR>
    ///     - Load NA2P or A2P dialog type from command code
    m2qp.cmd.code           = q_readbyte(&rxq);
    m2qp.cmd.ext            = (m2qp.cmd.code & 0x80) ? q_readbyte(&rxq) : 0;
    dll.comm.csmaca_params  = m2qp.cmd.ext & (M2_CSMACA_CAMASK | M2_CSMACA_NOCSMA);
    dll.comm.csmaca_params |= m2qp.cmd.code & M2_CSMACA_ARBMASK;
    cmd_opcode              = m2qp.cmd.code & M2OP_MASK;

    /// 2.  All Requests contain the dialog template, so load it.           <BR>
    ///     - [ num resp channels ] [ list of resp channels]                <BR>
    ///     - if number of resp channels is 0, use the current channel
    {
        ot_u8 timeout_code  = q_readbyte(&rxq);
        dll.comm.rx_timeout = otutils_calc_timeout(timeout_code);    // original contention period
        dll.comm.tc         = dll.comm.rx_timeout;  // contention period counter

        if (timeout_code & 0x80) {
            dll.comm.tx_channels    = q_readbyte(&rxq);
            dll.comm.tx_chanlist    = q_markbyte(&rxq, dll.comm.tx_channels);
        }
        else {
            dll.comm.tx_channels    = 1;
            dll.comm.tx_chanlist    = &dll.comm.scratch[0];
            dll.comm.scratch[0]     = session->channel;
        }
    }

    /// 3. Handle Command Queries (filtering)                               <BR>
    /// Multicast and anycast addressed requests include queries
    if (m2np.header.addr_ctl & 0x80) {
        score = sub_process_query(session);
    }

    /// 4. If the query is good (sometimes this is trivial):                <BR>
    ///    - Prepare the response header (same for all responses)           <BR>
    ///    - Run command-specific dialog data processing
    if (score >= 0) {
        q_empty(&txq); // Flush TX Queue

        if (m2qp.cmd.ext & M2CE_NORESP) {
            session->netstate  |= M2_NETFLAG_SCRAP;
        }
        else {
            ot_u8 addressing;
            session->netstate  &= ~M2_NETSTATE_TMASK;
            session->netstate  |= M2_NETSTATE_RESPTX;
            addressing          = ext_get_m2appflags();
            addressing         |= m2np.header.addr_ctl & 0x30;  // make unicast, retain VID & NLS
            m2np_header(session, addressing, 0);                // Create M2QP header
            q_writebyte(&txq, (M2TT_RESPONSE | cmd_opcode));    // Write Cmd code byte
        }

        switch ((cmd_opcode>>1) & 7) {
        case 0:
        case 1:
            break;
        case 2:
            sub_opgroup_shell();
            break;
        case 3:
        case 4:
            sub_opgroup_collection();
            break;
        case 5:
            break;
        case 6:
            sub_opgroup_datastream();
            break;
        case 7:
            sub_ack_datastream();
            break;
        }
    }
Example #2
0
int sub_getdecnum(int* status, FILE* stream, Queue* msg) {
    int     digits;
    char    next;
    char    buf[16];
    int     sign    = 1;
    int     force_u = 0;
    int     number  = 0;
    int     i       = 0;
    int     size    = 0;
    
    // Buffer until whitespace or ')' delimiter 
    digits = sub_buffernum(status, stream, buf, 15);
    
    // Deal with leading minus sign
    if (buf[i] == '-') {
        sign = -1;
        i++;
    }
    
    // Go through the digits & footer
    // - load in numerical value, one digit at a time
    // - also look for the type footer: ul, us, uc, u, l, s, c, or none
    while (i < digits) {
        if ((buf[i] >= '0') && (buf[i] <= '9')) {
            number *= 10;
            number += (buf[i++] - '0');
        }
        else {
            force_u = (buf[i] == 'u');
            i      += force_u;

            if (buf[i] == 'c')      size = 1;   // c: char (1 byte)
            else if (buf[i] == 's') size = 2;   // s: short (2 bytes)
            else if (buf[i] == 'l') size = 3;   // l: long (4 bytes)
            break;
        }
    }
    
    // Determine size in case where footer is not explicitly provided
    if (size == 0) {
        int j;
        int bound[] = {128, 256, 32768, 65536, 0, 0};
        int max     = number - (sign < 0);
        
        for (j=force_u, size=1;  ; j+=2, size++) {
            if ((bound[j]==0) || (bound[j]>=max)) break;
        }
    }

    number *= sign;

    switch (size & 3) {
        case 0:
        case 1: q_writebyte(msg, (ot_u8)number);
                break;
        
        case 2: q_writeshort(msg, (ot_u16)number);
                break;
        
        case 3: size = 4;
                q_writelong(msg, (ot_u32)number);
                break;
    }
    
    return size;
}
Example #3
0
OT_WEAK void alp_stream_id_tmpl(ot_queue* out_q, void* data_type) { 
    if _PTR_TEST(data_type) {
        q_writebyte(out_q, ((id_tmpl*)data_type)->length);
        q_writestring(out_q, ((id_tmpl*)data_type)->value, ((id_tmpl*)data_type)->length);
    }
}
Example #4
0
OT_WEAK void alp_stream_u32(ot_queue* out_q, void* data_type) {
    q_writebyte(out_q, *(ot_u32*)data_type);
}
Example #5
0
void sub_build_uhfmsg(ot_int* buffer) {
/// This is the routine that builds the DASH7 UDP generic protocol message.
/// The protocol has data elements marked by a letter (T, V, R, E, D) that
/// signify Temperature, Voltage, RSSI (LF), PaLFi wake Event, and RX Data.
/// The elements are fixed/known length.
    session_tmpl    s_tmpl;
    command_tmpl    c_tmpl;
    ot_u8*          data_start;
    ot_u8           status;

    // Create a new session: you could change these parameters
    // Use "CHAN1" for odd events, "CHAN2" for even events
    s_tmpl.channel      = (palfi.wake_event & 1) ? ALERT_CHAN1 : ALERT_CHAN2;     
    s_tmpl.subnetmask   = 0;        // Use default subnet
    s_tmpl.flagmask     = 0;        // Use default app-flags
    s_tmpl.timeout      = 10;       // Do CSMA for no more than 10 ticks (~10 ms)
    otapi_new_session(&s_tmpl);
    
    // Broadcast request (takes no 2nd argument)
    otapi_open_request(ADDR_broadcast, NULL);
    
    // Insert Transport-Layer headers
    c_tmpl.type     = CMDTYPE_na2p_request;
    c_tmpl.opcode   = CMD_udp_on_file;
    c_tmpl.extension= CMDEXT_no_response;
    otapi_put_command_tmpl(&status, &c_tmpl);
    otapi_put_dialog_tmpl(&status, NULL);       // NULL = defaults
    
    // UDP Header
    q_writebyte(&txq, 255);        // Source Port: 255 (custom application port)
    q_writebyte(&txq, 255);        // Destination Port (same value)
    
    data_start = txq.putcursor;
    
    // Place temperature data
    q_writebyte(&txq, 'T');
    q_writeshort(&txq, buffer[0]);
    
    // Place Voltage data
    q_writebyte(&txq, 'V');
    q_writeshort(&txq, buffer[1]);
    
    // Place RSSI data
    q_writebyte(&txq, 'R');
    q_writestring(&txq, (ot_u8*)&palfi.rssi1, 3);

    // Place Action data
    q_writebyte(&txq, 'E');
    q_writebyte(&txq, (ot_int)palfi.wake_event);
    
    // Dump some received data
    if (palfi.wake_event) {
        q_writebyte(&txq, 'D');
        q_writestring(&txq, palfi.rxdata, 8);
    }
    
    // Store this information into the Port 255 file for continuous, automated
    // reporting by DASH7/OpenTag until it is updated next time.  The length of 
    // this information is always 23 bytes.
    {
    	vlFILE* fp;
    	fp = ISF_open_su(255);
    	if (fp != NULL) {
    		vl_store(fp, 23, data_start);
    		vl_close(fp);
    	}
    }
    
    // Finish Message
    otapi_close_request();
}