/********************************************************************************
 * Copyright (c) 2021 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and
 * Document License (2015-05-13) which is available at
 * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document.
 *
 * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513
 ********************************************************************************/ /**
 * M-Bus master based on node-mbus
 */ import { MBusForm } from "./mbus" ; import { ProtocolClient , Content } from "@node-wot/core" ; import { SecurityScheme } from "@node-wot/td-tools" ; import { MBusConnection , PropertyOperation } from "./mbus-connection" ; import { Subscription } from "rxjs/Subscription" ; const DEFAULT_PORT = 805 ; const DEFAULT_TIMEOUT = 1000 ; export default class MBusClient implements ProtocolClient { private _connections : Map < string , MBusConnection > ; constructor ( ) { this . _connections = new Map ( ) ; } readResource ( form ) { return this . performOperation ( form ) as Promise < Content > ; } writeResource ( form , content ) { return new Promise < void > ( ( resolve , reject ) => { throw new Error ( "Method not implemented." ) ; } ) ; } invokeResource ( form , content ) { return new Promise < Content > ( ( resolve , reject ) => { throw new Error ( "Method not implemented." ) ; } ) ; } unlinkResource ( form ) { return new Promise < void > ( ( resolve , reject ) => { throw new Error ( "Method not implemented." ) ; } ) ; } public subscribeResource ( form , next , error ? , complete ? ) { return new Promise < Subscription > ( ( resolve , reject ) => { throw new Error ( "Method not implemented." ) ; } ) ; } async start ( ) { } async stop ( ) { this . _connections . forEach ( ( connection ) => { connection . close ( ) ; } ) ; } setSecurity ( metadata , credentials ? ) { return false ; } private async performOperation ( form ) { const parsed = new URL ( form . href ) ; const port = parsed . port ? parseInt ( parsed . port , 10 ) : DEFAULT_PORT ; form = this . validateAndFillDefaultForm ( form ) ; const host = parsed . hostname ; const hostAndPort = host + ":" + port ; this . overrideFormFromURLPath ( form ) ; let connection = this . _connections . get ( hostAndPort ) ; if ( ! connection ) { console . debug ( "[binding-mbus]" , "Creating new MbusConnection for " , hostAndPort ) ; this . _connections . set ( hostAndPort , new MBusConnection ( host , port , { connectionTimeout : form [ "mbus:timeout" ] || DEFAULT_TIMEOUT } ) ) ; connection = this . _connections . get ( hostAndPort ) ; } else { console . debug ( "[binding-mbus]" , "Reusing MbusConnection for " , hostAndPort ) ; } const operation = new PropertyOperation ( form ) ; connection . enqueue ( operation ) ; return connection . execute ( operation ) ; } private overrideFormFromURLPath ( input ) { const parsed = new URL ( input . href ) ; const pathComp = parsed . pathname . split ( "/" ) ; const query = parsed . searchParams ; input [ "mbus:unitID" ] = parseInt ( pathComp [ 1 ] , 10 ) || input [ "mbus:unitID" ] ; input [ "mbus:offset" ] = parseInt ( query . get ( "offset" ) , 10 ) || input [ "mbus:offset" ] ; input [ "mbus:timeout" ] = parseInt ( query . get ( "timeout" ) , 10 ) || input [ "mbus:timeout" ] ; } private validateAndFillDefaultForm ( form ) { const result = { ... form } ; if ( form [ "mbus:unitID" ] === undefined || form [ "mbus:unitID" ] === null ) { throw new Error ( "Malformed form: unitID must be defined" ) ; } if ( form [ "mbus:offset" ] === undefined || form [ "mbus:offset" ] === null ) { throw new Error ( "Malformed form: offset must be defined" ) ; } result [ "mbus:timeout" ] = form [ "mbus:timeout" ] ? form [ "mbus:timeout" ] : DEFAULT_TIMEOUT ; return result ; } }