forked from microsoft/devicescript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdeploy.ts
More file actions
145 lines (125 loc) · 3.92 KB
/
deploy.ts
File metadata and controls
145 lines (125 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import {
bufferEq,
delay,
DeviceScriptManagerCmd,
DeviceScriptManagerReg,
JDService,
OutPipe,
prettySize,
SettingsClient,
sha256,
SRV_WIFI,
toHex,
WifiCmd,
} from "jacdac-ts"
import { devsStartWithNetwork } from "./build"
import { error } from "./command"
import { readCompiled } from "./run"
import { BuildOptions } from "./sideprotocol"
import { DISABLE_AUTO_START_KEY } from "./devtools"
export interface RunOptions {
tcp?: boolean
}
export async function deployScript(
fn: string,
options: RunOptions & BuildOptions
) {
const inst = await devsStartWithNetwork(options)
inst.deployHandler = code => {
if (code) error(`deploy error ${code}`)
process.exit(code)
}
const prog = await readCompiled(fn, options)
const r = inst.devsClientDeploy(prog.binary)
if (r) throw new Error("deploy error: " + r)
console.log(`remote-deployed ${fn}`)
}
export async function deploySettingsToService(
settingsService: JDService,
settings: Record<string, Uint8Array>
) {
if (!settings) return
// handle special settings
const { WIFI_SSID, WIFI_PWD, ...rest } = settings
// apply generic settings
if (Object.keys(rest)) {
const client = new SettingsClient(settingsService)
for (const key in rest) {
console.debug(`deploying setting ${key}...`)
const value = settings[key]
await client.setValue(key, value)
}
}
// wifi settings
if (WIFI_SSID) {
const wifis = settingsService.device.services({
serviceClass: SRV_WIFI,
})
const ssid = JSON.parse(Buffer.from(WIFI_SSID).toString("utf-8"))
const pwd = JSON.parse(
WIFI_PWD ? Buffer.from(WIFI_PWD).toString("utf-8") : '""'
)
for (const wifi of wifis) {
console.debug(`deploying wifi credentials`)
await wifi.sendCmdPackedAsync(WifiCmd.AddNetwork, [ssid, pwd], true)
}
}
}
export interface DeployOptions {
settingsService?: JDService
settings?: Record<string, Uint8Array>
noRun?: boolean
}
export async function deployToService(
service: JDService,
bytecode: Uint8Array,
options: DeployOptions = {}
) {
console.log(`deploy to ${service.device}`)
const { settingsService, settings, noRun } = options
const autostart = service.register(DeviceScriptManagerReg.Autostart)
const running = service.register(DeviceScriptManagerReg.Running)
const sha = service.register(DeviceScriptManagerReg.ProgramSha256)
await sha.refresh()
await autostart.refresh()
const oldAutoStart = autostart.boolValue
// disable autostart
await autostart.sendSetBoolAsync(false)
await running.sendSetBoolAsync(false)
await delay(10)
if (sha.data?.length == 32) {
const exp = await sha256([bytecode])
if (bufferEq(exp, sha.data)) {
console.log(` sha256 match ${toHex(exp)}, skip`)
// stop running
await running.sendSetBoolAsync(false)
await delay(10)
// deploy settings if needed
if (settingsService)
await deploySettingsToService(settingsService, settings)
await startAgain()
return
}
}
await OutPipe.sendBytes(
service,
DeviceScriptManagerCmd.DeployBytecode,
bytecode,
p => {
// console.debug(` prog: ${(p * 100).toFixed(1)}%`)
}
)
if (settingsService)
await deploySettingsToService(settingsService, settings)
await startAgain()
console.log(` --> done, ${prettySize(bytecode.length)}`)
async function startAgain() {
if (noRun) return
if (
!service.device.bus.nodeData[DISABLE_AUTO_START_KEY] &&
oldAutoStart !== undefined
)
await autostart.sendSetBoolAsync(oldAutoStart)
await running.sendSetBoolAsync(true)
}
}