import { OptionName , NamedOption , Packet } from 'coap-packet' ; import { CoapPacket , Option , OptionValue , Block } from '../models/models' ; import { toBinary , fromBinary , isIgnored } from './option_converter' ; import capitalize from 'capitalize' ; const codes = { 0.01 : 'GET' , 0.02 : 'POST' , 0.03 : 'PUT' , 0.04 : 'DELETE' , 0.05 : 'FETCH' , 0.06 : 'PATCH' , 0.07 : 'iPATCH' } ; export function genAck ( request ) { return { messageId : request . messageId , code : '0.00' , options : [ ] , confirmable : false , ack : true , reset : false } ; } const optionAliases = { 'Content-Type' : 'Content-Format' , Etag : 'ETag' } ; export function setOption ( packet , name , values ) { name = capitalize . words ( name ) ; name = optionAliases [ name ] ?? name ; const optionName = name as OptionName ; if ( isIgnored ( name ) ) { return ; } packet . options = packet . options ?. filter ( ( option ) => { return option . name !== name ; } ) ; if ( ! Array . isArray ( values ) ) { packet . options ?. push ( { name : optionName , value : toBinary ( name , values ) } ) ; } else { for ( const value of values ) { packet . options ?. push ( { name : optionName , value } ) ; } } } export function toCode ( code ) { if ( typeof code === 'string' ) { return code ; } const first = Math . floor ( code / 100 ) ; const second = code - first * 100 ; let result = '' ; result += String ( first ) + '.' ; if ( second < 10 ) { result += '0' ; } result += String ( second ) ; return result ; } export function packetToMessage ( dest , packet ) { const options = packet . options ?? [ ] ; const paths = [ ] ; const queries = [ ] ; let query = '' ; dest . payload = packet . payload ; dest . options = packet . options ; dest . code = packet . code ; dest . method = codes [ dest . code ] ; dest . headers = { } ; for ( let i = 0 ; i < options . length ; i ++ ) { const option = options [ i ] ; if ( typeof option . name !== 'string' ) { continue ; } if ( option . name === 'Uri-Path' ) { paths . push ( option . value ) ; } if ( option . name === 'Uri-Query' ) { queries . push ( option . value ) ; } option . value = fromBinary ( option . name , option . value ) ; if ( option . value != null && ! Buffer . isBuffer ( option . value ) ) { dest . headers [ option . name ] = option . value ; } } if ( dest . headers [ 'Content-Format' ] != null ) { dest . headers [ 'Content-Type' ] = dest . headers [ 'Content-Format' ] ; } query = queries . join ( '&' ) ; let url = '/' + paths . join ( '/' ) ; if ( query !== '' ) { url += '?' + query ; } dest . url = url ; } export function hasOption ( options , name ) { for ( const option of options ) { if ( option . name === name ) { return true ; } } return null ; } param options param name returns export function getOption ( options , name ) { if ( options == null ) { return null ; } for ( const option of options ) { if ( option . name === name ) { return option . value ; } } return null ; } param options param name returns export function removeOption ( options , name ) { let result = false ; options . forEach ( ( option , index ) => { if ( option . name === name ) { options . splice ( index , 1 ) ; result = true ; } } ) ; return result ; } param block2Value returns export function parseBlock2 ( block2Value ) { let num ; switch ( block2Value . length ) { case 0 : return { more : 0 , size : 0 , num : 0 } ; case 1 : num = block2Value [ 0 ] >> 4 ; break ; case 2 : num = ( block2Value [ 0 ] * 256 + block2Value [ 1 ] ) >> 4 ; break ; case 3 : num = ( block2Value [ 0 ] * 256 * 256 + block2Value [ 1 ] * 256 + block2Value [ 2 ] ) >> 4 ; break ; default : return null ; } const lastByte = block2Value . slice ( - 1 ) [ 0 ] ; if ( ( lastByte & 7 ) === 7 ) { return null ; } const more = ( lastByte & 8 ) >> 3 ; return { more , num , size : Math . pow ( 2 , ( lastByte & 7 ) + 4 ) } ; } param requestedBlock returns export function createBlock2 ( requestedBlock ) { const szx = Math . log ( requestedBlock . size ) / Math . log ( 2 ) - 4 ; const m = requestedBlock . more ; const num = requestedBlock . num ; let extraNum ; let byte = 0 ; byte |= szx ; byte |= m << 3 ; byte |= ( num & 0xf ) << 4 ; if ( num <= 0xf ) { return Buffer . of ( byte ) ; } else if ( num <= 0xfff ) { extraNum = Buffer . of ( num / 16 ) ; } else if ( num <= 0xfffff ) { extraNum = Buffer . alloc ( 2 ) ; extraNum . writeUInt16BE ( num >> 4 , 0 ) ; } else { return null ; } return Buffer . concat ( [ extraNum , Buffer . of ( byte ) ] ) ; } param previous param current returns export function or ( previous , current ) { return previous || current ; } param optionName returns export function isOption ( optionName ) { return ( option ) => { return option . name === optionName ; } ; } export function isNumeric ( n ) { return ! isNaN ( parseFloat ( n ) ) && isFinite ( n ) ; } export function isBoolean ( n ) { return typeof ( n ) === 'boolean' ; }