start to parse variable data blocks, tests are yet missing, coding tables and especially encoder functions not completex
This commit is contained in:
parent
49a6a46052
commit
f1830497b0
@ -1,6 +1,10 @@
|
|||||||
|
import {MeterbusLibUtils} from './utils'
|
||||||
|
|
||||||
|
|
||||||
export namespace MeterbusLibCodeTables {
|
export namespace MeterbusLibCodeTables {
|
||||||
export const MEDIUM_CODE : string[] =
|
export const MEDIUM_CODE : string[] =
|
||||||
['Other',
|
[
|
||||||
|
'Other',
|
||||||
'Oil',
|
'Oil',
|
||||||
'Electrity',
|
'Electrity',
|
||||||
'Gas',
|
'Gas',
|
||||||
@ -28,4 +32,64 @@ export namespace MeterbusLibCodeTables {
|
|||||||
'A/D Converter',
|
'A/D Converter',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export const DIF_FUNCTION_FIELD : string[] =
|
||||||
|
[
|
||||||
|
'Instantaneous value',
|
||||||
|
'Maximum value',
|
||||||
|
'Minimum value',
|
||||||
|
'Value during error state'
|
||||||
|
]
|
||||||
|
|
||||||
|
export class DCFt {
|
||||||
|
name : string
|
||||||
|
length : number
|
||||||
|
encoder : (v: number[]) => any
|
||||||
|
constructor(n : string, l : number, e : (v: number[]) => any) {
|
||||||
|
this.name = n
|
||||||
|
this.length = l
|
||||||
|
this.encoder = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DIF_CODING_FIELD : DCFt[] =
|
||||||
|
[
|
||||||
|
new DCFt('No Data', 0, (x)=>{ return x}),
|
||||||
|
new DCFt('8 Bit Integer', 1, (x)=>{ return x[0]}),
|
||||||
|
new DCFt('16 Bit Integer', 2, (x)=>{ return (x[1] << 8) + x[0]}),
|
||||||
|
new DCFt('24 Bit Integer', 3, (x)=>{ return (x[2] << 16) + (x[1] << 8) + x[0]}),
|
||||||
|
new DCFt('32 Bit Integer', 4, (x)=>{ return (x[3] << 24) + (x[2] << 16) + (x[1] << 8) + x[0]}),
|
||||||
|
new DCFt('32 Bit Real', 4, (x)=>{ return x}), // FIXME
|
||||||
|
new DCFt('48 Bit Integer', 6, (x)=>{ return (x[5] << 40) + (x[4] << 32) + (x[3] << 24) + (x[2] << 16) + (x[1] << 8) + x[0]}),
|
||||||
|
new DCFt('64 Bit Integer', 8, (x)=>{ return (x[7] << 56) + (x[6] << 48) + (x[5] << 40) + (x[4] << 32) + (x[3] << 24) + (x[2] << 16) + (x[1] << 8) + x[0]}),
|
||||||
|
new DCFt('Selection for Readout', 0, (x)=>{ return x}),
|
||||||
|
new DCFt('2 Digit BCD', 1, (x)=>{ return MeterbusLibUtils.bcd(x)}),
|
||||||
|
new DCFt('4 Digit BCD', 2, (x)=>{ return MeterbusLibUtils.bcd(x)}),
|
||||||
|
new DCFt('6 Digit BCD', 3, (x)=>{ return MeterbusLibUtils.bcd(x)}),
|
||||||
|
new DCFt('8 Digit BCD', 4, (x)=>{ return MeterbusLibUtils.bcd(x)}),
|
||||||
|
new DCFt('variable length', -1, (x)=>{ return x}),
|
||||||
|
new DCFt('12 Digit BCD', 6, (x)=>{ return MeterbusLibUtils.bcd(x)}),
|
||||||
|
new DCFt('Special Function', 0, (x)=>{ return x})
|
||||||
|
]
|
||||||
|
|
||||||
|
/*
|
||||||
|
DATA_FIELD_CODES = (
|
||||||
|
('No Data', 0, None),
|
||||||
|
('8 Bit Integer', 1, lambda x: x[0]),
|
||||||
|
('16 Bit Integer', 2, lambda x: (x[1] << 8) + x[0]),
|
||||||
|
('24 Bit Integer', 3, lambda x: (x[2] << 16) + (x[1] << 8) + x[0]),
|
||||||
|
('32 Bit Integer', 4, lambda x: (x[3] << 24) + (x[2] << 16) + (x[1] << 8) + x[0]),
|
||||||
|
('32 Bit Real', 4, lambda x: struct.unpack('f', str(bytearray(x)))[0]),
|
||||||
|
('48 Bit Integer', 6, lambda x: (x[5] << 40) + (x[4] << 32) + (x[3] << 24) + (x[2] << 16) + (x[1] << 8) + x[0]),
|
||||||
|
('64 Bit Integer', 8, lambda x: (x[7] << 56) + (x[6] << 48) + (x[5] << 40) + (x[4] << 32) + (x[3] << 24) + (x[2] << 16) + (x[1] << 8) + x[0]),
|
||||||
|
('Selection for Readout', 0, None),
|
||||||
|
('2 Digit BCD', 1, lambda x: MeterbusTypeConversion.bcd(x)),
|
||||||
|
('4 Digit BCD', 2, lambda x: MeterbusTypeConversion.bcd(x)),
|
||||||
|
('6 Digit BCD', 3, lambda x: MeterbusTypeConversion.bcd(x)),
|
||||||
|
('8 Digit BCD', 4, lambda x: MeterbusTypeConversion.bcd(x)),
|
||||||
|
('variable length', -1, None),
|
||||||
|
('12 Digit BCD', 6, lambda x: MeterbusTypeConversion.bcd(x)),
|
||||||
|
('Special Function', 0, None),
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
165
src/longframe.ts
165
src/longframe.ts
@ -6,6 +6,8 @@ import {MeterbusLibCodeTables} from './codetables'
|
|||||||
export namespace MeterbusLibLongFrame {
|
export namespace MeterbusLibLongFrame {
|
||||||
export class LongFrame extends MeterbusLibFrames.ControlFrame {
|
export class LongFrame extends MeterbusLibFrames.ControlFrame {
|
||||||
private _fixedDataHeader : FixedDataHeader
|
private _fixedDataHeader : FixedDataHeader
|
||||||
|
private _variableDataBlocks : DataBlock[] = []
|
||||||
|
|
||||||
get fixedDataHeader() : FixedDataHeader { return this._fixedDataHeader }
|
get fixedDataHeader() : FixedDataHeader { return this._fixedDataHeader }
|
||||||
|
|
||||||
constructor(telegram : number[]) {
|
constructor(telegram : number[]) {
|
||||||
@ -16,6 +18,16 @@ export namespace MeterbusLibLongFrame {
|
|||||||
super.parse2() // control frame parse2 method
|
super.parse2() // control frame parse2 method
|
||||||
this._fixedDataHeader = new FixedDataHeader(this._telegram.slice(7, 19))
|
this._fixedDataHeader = new FixedDataHeader(this._telegram.slice(7, 19))
|
||||||
this._fixedDataHeader.parse()
|
this._fixedDataHeader.parse()
|
||||||
|
|
||||||
|
let consumed : number = 0
|
||||||
|
while (true) {
|
||||||
|
let die : DataBlock =
|
||||||
|
new DataBlock(this._telegram.slice(19 + consumed))
|
||||||
|
die.parse()
|
||||||
|
this._variableDataBlocks.push(die)
|
||||||
|
consumed += die.consumed
|
||||||
|
break //FIXME
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,4 +73,157 @@ export namespace MeterbusLibLongFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export abstract class ADataBlock {
|
||||||
|
protected __consumed : number = 0
|
||||||
|
|
||||||
|
get consumed() : number {
|
||||||
|
return this.__consumed
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract parse() : void
|
||||||
|
|
||||||
|
toJSON() : any {
|
||||||
|
console.log("x")
|
||||||
|
return MeterbusLibUtils.jsonPrepaper(this, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
getJSON() : string {
|
||||||
|
return JSON.stringify(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DataBlock extends ADataBlock {
|
||||||
|
private _content : VariableDataBlock | ManufacturerSpecificData
|
||||||
|
|
||||||
|
constructor(data : number[]) {
|
||||||
|
super()
|
||||||
|
if ((data[0] & 0x0f) == 0x0f) {
|
||||||
|
this._content = new ManufacturerSpecificData(data)
|
||||||
|
} else {
|
||||||
|
this._content = new VariableDataBlock(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
parse() : void {
|
||||||
|
this._content.parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON() : any {
|
||||||
|
return MeterbusLibUtils.jsonPrepaper(this._content, [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DIF {
|
||||||
|
raw : number
|
||||||
|
function : number
|
||||||
|
coding : number
|
||||||
|
lsb : number
|
||||||
|
extension : number
|
||||||
|
|
||||||
|
toJSON() : any {
|
||||||
|
let dup = MeterbusLibUtils.clone(this)
|
||||||
|
dup.function = MeterbusLibCodeTables.DIF_FUNCTION_FIELD[dup.function]
|
||||||
|
dup.coding = MeterbusLibCodeTables.DIF_CODING_FIELD[dup.coding].name
|
||||||
|
return dup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DIFE {
|
||||||
|
raw : number
|
||||||
|
extension : number
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VIF {
|
||||||
|
raw : number
|
||||||
|
unitAndMultiplier : number
|
||||||
|
extension : number
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VIFE {
|
||||||
|
raw : number
|
||||||
|
extension : number
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VariableDataBlock extends ADataBlock {
|
||||||
|
private _type : string = "VDB"
|
||||||
|
private __indata : number[]
|
||||||
|
private _dif : DIF
|
||||||
|
private _dife : DIFE[] = []
|
||||||
|
private _vif : VIF
|
||||||
|
private _vife : VIFE[] = []
|
||||||
|
private _data : number[]
|
||||||
|
private _value : any
|
||||||
|
|
||||||
|
constructor(data : number[]) {
|
||||||
|
super()
|
||||||
|
this.__indata = data
|
||||||
|
}
|
||||||
|
|
||||||
|
parse() : void {
|
||||||
|
this._dif = new DIF()
|
||||||
|
this._dif.raw = this.__indata[0]
|
||||||
|
this.__consumed++
|
||||||
|
this._dif.function = (this._dif.raw & 0x30) >> 4
|
||||||
|
this._dif.coding = this._dif.raw & 0x0f
|
||||||
|
this._dif.lsb = (this._dif.raw & 0x40) >> 6
|
||||||
|
this._dif.extension = (this._dif.raw & 0x80) >> 7
|
||||||
|
|
||||||
|
if (this._dif.extension == 1) {
|
||||||
|
while (true) {
|
||||||
|
let dife = new DIFE()
|
||||||
|
dife.raw = this.__indata[this.__consumed]
|
||||||
|
this.__consumed++
|
||||||
|
dife.extension = (dife.raw & 0x80) >> 7
|
||||||
|
this._dife.push(dife)
|
||||||
|
if (dife.extension == 0) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._vif = new VIF()
|
||||||
|
this._vif.raw = this.__indata[this.__consumed]
|
||||||
|
this.__consumed++
|
||||||
|
this._vif.unitAndMultiplier = this._vif.raw & 0x7f
|
||||||
|
this._vif.extension = (this._vif.raw & 0x80) >> 7
|
||||||
|
|
||||||
|
if (this._vif.extension == 1) {
|
||||||
|
while (true) {
|
||||||
|
let vife = new VIFE()
|
||||||
|
vife.raw = this.__indata[this.__consumed]
|
||||||
|
this.__consumed++
|
||||||
|
vife.extension = (vife.raw & 0x80) >> 7
|
||||||
|
this._vife.push(vife)
|
||||||
|
if (vife.extension == 0) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let dcf : MeterbusLibCodeTables.DCFt = MeterbusLibCodeTables.DIF_CODING_FIELD[this._dif.coding]
|
||||||
|
this._data = this.__indata.slice(this.__consumed,
|
||||||
|
this.__consumed + dcf.length)
|
||||||
|
this.__consumed += dcf.length
|
||||||
|
|
||||||
|
console.log(dcf.encoder)
|
||||||
|
this._value = dcf.encoder(this._data)
|
||||||
|
console.log(this._value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ManufacturerSpecificData extends ADataBlock {
|
||||||
|
private _type : string = "MSD"
|
||||||
|
private _data : number[]
|
||||||
|
|
||||||
|
constructor(data : number[]) {
|
||||||
|
super()
|
||||||
|
this._data = data
|
||||||
|
}
|
||||||
|
|
||||||
|
parse() : void {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -180,6 +180,7 @@ describe('The Meterbus Longframe Library', () => {
|
|||||||
.to.deep.equal([0,0])
|
.to.deep.equal([0,0])
|
||||||
})
|
})
|
||||||
it('should prepare itself as JSON', () => {
|
it('should prepare itself as JSON', () => {
|
||||||
|
console.log((telegram.frame as MeterbusLibLongFrame.LongFrame).getJSON())
|
||||||
expect((telegram.frame as MeterbusLibLongFrame.LongFrame).getJSON()).to.equal(json_1phase_electric)
|
expect((telegram.frame as MeterbusLibLongFrame.LongFrame).getJSON()).to.equal(json_1phase_electric)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -49,3 +49,16 @@ describe('The jsonPrepare function in the Meterbus Library Utils', () => {
|
|||||||
expect(MeterbusLibUtils.jsonPrepaper(objIn, [])).to.deep.equal(objOut)
|
expect(MeterbusLibUtils.jsonPrepaper(objIn, [])).to.deep.equal(objOut)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('The clone function in the Meterbus Library Utils', () => {
|
||||||
|
it('should clone the attributes of an object', () => {
|
||||||
|
let objIn = {'a': 1, 'b': 2}
|
||||||
|
let objOut = {'a': 1, 'b': 2}
|
||||||
|
expect(MeterbusLibUtils.clone(objIn)).to.deep.equal(objOut)
|
||||||
|
})
|
||||||
|
it('should not just return the same object', () => {
|
||||||
|
let objIn = {'a': 1, 'b':2}
|
||||||
|
let objOut = objIn
|
||||||
|
expect(MeterbusLibUtils.clone(objIn)).to.not.equal(objOut)
|
||||||
|
})
|
||||||
|
})
|
@ -24,5 +24,14 @@ export namespace MeterbusLibUtils {
|
|||||||
}
|
}
|
||||||
return dup
|
return dup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clone(obj:any) : any {
|
||||||
|
let dup = {}
|
||||||
|
for (let key in obj) {
|
||||||
|
dup[key] = obj[key]
|
||||||
|
}
|
||||||
|
return dup
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user