fix: updated cloud adapter server

This commit is contained in:
Peli de Halleux 2023-03-08 21:05:17 +00:00
Родитель 97b95358ac
Коммит 7095219bd4
2 изменённых файлов: 17 добавлений и 108 удалений

@ -1 +1 @@
Subproject commit 7ccd0b2461a2dae261b387de42a2683eeb44c3b5
Subproject commit 4edbe62754ccf5415f8af9ec25bb0bae315d8e11

Просмотреть файл

@ -1,50 +1,30 @@
import {
TIMEOUT,
DEVICE_CHANGE,
DISCONNECT,
CloudAdapterCmd,
CloudAdapterCommandStatus,
CloudAdapterEvent,
CloudAdapterReg,
SELF_ANNOUNCE,
SRV_CLOUD_ADAPTER,
CHANGE,
CloudAdapterCmdPack,
} from "../jdom/constants"
import { jdpack } from "../jdom/pack"
import { Packet } from "../jdom/packet"
import { JDRegisterServer } from "../jdom/servers/registerserver"
import { JDServerOptions, JDServiceServer } from "../jdom/servers/serviceserver"
export const UPLOAD = "upload"
export const UPLOAD_JSON = "upload"
export const UPLOAD_BIN = "uploadBin"
export const CLOUD_COMMAND = "cloudCommand"
export interface CloudAdapterUploadRequest {
label: string
args: number[]
export interface CloudAdapterUploadJSONRequest {
json: string
}
export interface CloudAdapterUploadBinRequest {
data: Uint8Array
}
export interface CloudAdapterCommandResponse {
status: CloudAdapterCommandStatus
args: number[]
}
export class CloudAdapterServer extends JDServiceServer {
readonly connectedRegister: JDRegisterServer<[boolean]>
readonly connectionNameRegister: JDRegisterServer<[string]>
private seqNo = 0
private pending: Record<
string,
{
timeout: number
resolve: (resp: CloudAdapterCommandResponse) => void
reject: (reason?: unknown) => void
}
> = {}
readonly controlled: boolean
constructor(
@ -63,17 +43,14 @@ export class CloudAdapterServer extends JDServiceServer {
CloudAdapterReg.ConnectionName,
[options?.connectionName || ""]
)
this.addCommand(CloudAdapterCmd.Upload, this.handleUpload.bind(this))
this.addCommand(
CloudAdapterCmd.UploadBin,
CloudAdapterCmd.UploadJson,
this.handleUpload.bind(this)
)
this.addCommand(
CloudAdapterCmd.UploadBinary,
this.handleUploadBin.bind(this)
)
this.addCommand(
CloudAdapterCmd.AckCloudCommand,
this.handleAckCloudCommand.bind(this)
)
this.on(DEVICE_CHANGE, this.handleDeviceChange.bind(this))
this.connectedRegister.on(CHANGE, () =>
this.sendEvent(CloudAdapterEvent.Change)
)
@ -82,13 +59,6 @@ export class CloudAdapterServer extends JDServiceServer {
)
}
private handleDeviceChange() {
if (this.device) {
this.device.on(DISCONNECT, this.clearPending.bind(this))
this.device.on(SELF_ANNOUNCE, this.gcPending.bind(this))
}
}
get connected() {
return this.connectedRegister.values()[0]
}
@ -106,8 +76,8 @@ export class CloudAdapterServer extends JDServiceServer {
return
}
const [label, args] = pkt.jdunpack<[string, number[]]>("z f64[]")
this.upload(label, args)
const [json] = pkt.jdunpack<[string]>(CloudAdapterCmdPack.UploadJson)
this.uploadJSON(json)
}
private async handleUploadBin(pkt: Packet) {
@ -120,74 +90,13 @@ export class CloudAdapterServer extends JDServiceServer {
this.uploadBin(data)
}
upload(label: string, args: number[]) {
//console.log("cloud: upload", { label, args })
this.emit(UPLOAD, <CloudAdapterUploadRequest>{ label, args })
}
uploadBin(data: Uint8Array) {
//console.log("cloud: upload bin", { data })
this.emit(UPLOAD_BIN, <CloudAdapterUploadBinRequest>{ data })
}
sendCloudCommand(
method: string,
args: number[],
timeout = 1000
): Promise<CloudAdapterCommandResponse> {
if (!this.connected) {
console.debug(`cloud: cancel send, not connected`)
return
}
const seqNo = this.seqNo++
const payload = jdpack<[number, string, [number][]]>("u32 z r: f64", [
seqNo,
method,
args.map(v => [v]),
])
return new Promise<CloudAdapterCommandResponse>((resolve, reject) => {
console.log(
`cloud: send ${seqNo} (${Object.keys(seqNo).length} pending)`
)
this.pending[seqNo] = {
timeout: this.device.bus.timestamp + timeout,
resolve,
reject,
}
this.sendEvent(CloudAdapterEvent.CloudCommand, payload)
uploadJSON(json: string) {
this.emit(UPLOAD_JSON, <CloudAdapterUploadJSONRequest>{
json,
})
}
private async handleAckCloudCommand(pkt: Packet) {
const [seqNo, status, args] =
pkt.jdunpack<[number, CloudAdapterCommandStatus, number[]]>(
"u32 u32 f64[]"
)
console.log("cloud: ack-invoke", seqNo, status, args)
const resp = { status, args }
const req = this.pending[seqNo]
if (req) {
delete this.pending[seqNo]
req.resolve(resp)
}
}
private gcPending() {
const now = this.device.bus.timestamp
Object.entries(this.pending)
.filter(([, req]) => req.timeout > now)
.map(([key]) => {
const reject = this.pending[key]?.reject
delete this.pending[key]
return reject
})
.filter(r => !!r)
.forEach(r => r(TIMEOUT))
}
private clearPending() {
const p = this.pending
this.pending = {}
Object.values(p).forEach(({ reject }) => reject())
uploadBin(data: Uint8Array) {
this.emit(UPLOAD_BIN, <CloudAdapterUploadBinRequest>{ data })
}
}