Skip to content

Commit 15bb109

Browse files
authored
Merge pull request #435 from PlayerData/explicit-zip
feat: Explicitly set either bin or zip upgrade file
2 parents f6b0501 + 8200464 commit 15bb109

File tree

11 files changed

+109
-185
lines changed

11 files changed

+109
-185
lines changed

example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"expo-document-picker": "13.0.1",
1717
"expo-splash-screen": "0.29.18",
1818
"lodash": "4.17.21",
19-
"react": "19.0.0",
19+
"react": "18.3.1",
2020
"react-native": "0.76.3",
2121
"react-native-ble-plx": "3.2.1",
2222
"react-native-toast-message": "2.2.1"

example/src/App.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { UpgradeMode } from '@playerdata/react-native-mcu-manager';
1+
import {
2+
UpgradeFileType,
3+
UpgradeMode,
4+
} from '@playerdata/react-native-mcu-manager';
25

36
import React, { useState } from 'react';
47
import {
@@ -36,6 +39,9 @@ export default function App() {
3639
const [selectedDeviceName, setSelectedDeviceName] = useState<string | null>(
3740
null
3841
);
42+
const [fileType, setFileType] = useState<UpgradeFileType>(
43+
UpgradeFileType.BIN
44+
);
3945
const [upgradeMode, setUpgradeMode] = useState<UpgradeMode | undefined>(
4046
undefined
4147
);
@@ -45,6 +51,7 @@ export default function App() {
4551
const { cancelUpdate, runUpdate, progress, state } = useFirmwareUpdate(
4652
selectedDeviceId,
4753
selectedFile?.uri || null,
54+
fileType,
4855
upgradeMode
4956
);
5057

@@ -98,6 +105,21 @@ export default function App() {
98105
<Button onPress={() => pickFile()} title="Pick File" />
99106
</View>
100107

108+
<Text style={styles.block}>Step 2a - Select Update File Type</Text>
109+
110+
<View style={styles.block}>
111+
<Button
112+
disabled={fileType === UpgradeFileType.BIN}
113+
title="BIN"
114+
onPress={() => setFileType(UpgradeFileType.BIN)}
115+
/>
116+
<Button
117+
disabled={fileType === UpgradeFileType.ZIP}
118+
title="ZIP"
119+
onPress={() => setFileType(UpgradeFileType.ZIP)}
120+
/>
121+
</View>
122+
101123
<Text style={styles.block}>Step 3 - Upgrade Mode</Text>
102124

103125
<View style={styles.block}>

example/src/useFirmwareUpdate.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
import { Upgrade, UpgradeMode } from '@playerdata/react-native-mcu-manager';
1+
import {
2+
Upgrade,
3+
UpgradeMode,
4+
UpgradeFileType,
5+
} from '@playerdata/react-native-mcu-manager';
26
import { useState, useEffect, useRef } from 'react';
37

48
const useFirmwareUpdate = (
59
bleId: string | null,
610
updateFileUri: string | null,
11+
upgradeFileType: UpgradeFileType,
712
upgradeMode?: UpgradeMode
813
) => {
914
const [progress, setProgress] = useState(0);
@@ -21,6 +26,7 @@ const useFirmwareUpdate = (
2126
{
2227
estimatedSwapTime: 60,
2328
upgradeMode,
29+
upgradeFileType,
2430
},
2531
setProgress,
2632
setState
@@ -32,7 +38,7 @@ const useFirmwareUpdate = (
3238
upgrade.cancel();
3339
upgrade.destroy();
3440
};
35-
}, [bleId, updateFileUri, upgradeMode]);
41+
}, [bleId, upgradeFileType, updateFileUri, upgradeMode]);
3642

3743
const runUpdate = async (): Promise<void> => {
3844
try {
@@ -41,7 +47,7 @@ const useFirmwareUpdate = (
4147
}
4248

4349
await upgradeRef.current.runUpgrade();
44-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
50+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
4551
} catch (ex: any) {
4652
setState(ex.message);
4753
}

pnpm-lock.yaml

Lines changed: 19 additions & 157 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

react-native-mcu-manager/android/src/main/java/uk/co/playerdata/reactnativemcumanager/DeviceUpgrade.kt

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import io.runtime.mcumgr.dfu.mcuboot.model.ImageSet
1515
import io.runtime.mcumgr.exception.McuMgrException
1616
import io.runtime.mcumgr.image.McuMgrImage
1717
import java.io.IOException
18-
import android.webkit.MimeTypeMap
1918

2019
val UpgradeModes =
2120
mapOf(
@@ -24,8 +23,17 @@ val UpgradeModes =
2423
3 to FirmwareUpgradeManager.Mode.TEST_ONLY
2524
)
2625

26+
enum class UpgradeFileType {
27+
BIN,
28+
ZIP,
29+
}
30+
31+
val UpgradeFileTypes = mapOf(
32+
0 to UpgradeFileType.BIN,
33+
1 to UpgradeFileType.ZIP,
34+
)
35+
2736
class DeviceUpgrade(
28-
private val id: String,
2937
device: BluetoothDevice,
3038
private val context: Context,
3139
private val updateFileUri: Uri,
@@ -72,15 +80,12 @@ class DeviceUpgrade(
7280
return inputStream.use { it.readBytes() }
7381
}
7482

75-
private fun extractImagesFrom(updateBundleUri: Uri): ImageSet {
76-
val fileExtension = MimeTypeMap.getFileExtensionFromUrl(updateBundleUri.toString())
77-
val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension)
83+
private fun extractImagesFrom(updateBundleUri: Uri, upgradeFileType: UpgradeFileType): ImageSet {
7884
val binData = uriToByteArray(updateBundleUri) ?: throw IOException("Failed to read update file")
7985

80-
if (mimeType == "application/zip") {
81-
return extractImagesFromZipFile(binData)
82-
} else {
83-
return extractImagesFromBinFile(binData)
86+
return when (upgradeFileType) {
87+
UpgradeFileType.BIN -> extractImagesFromBinFile(binData)
88+
UpgradeFileType.ZIP -> extractImagesFromZipFile(binData)
8489
}
8590
}
8691

@@ -95,18 +100,19 @@ class DeviceUpgrade(
95100
}
96101

97102
private fun extractImagesFromZipFile(zipData: ByteArray): ImageSet {
98-
return ZipPackage(zipData).getBinaries();
103+
return ZipPackage(zipData).getBinaries()
99104
}
100105

101106
private fun doUpdate(updateBundleUri: Uri) {
102107
val estimatedSwapTime = updateOptions.estimatedSwapTime * 1000
103108
val modeInt = updateOptions.upgradeMode ?: 1
109+
val upgradeFileType = UpgradeFileTypes[updateOptions.upgradeFileType] ?: UpgradeFileType.BIN
104110
val upgradeMode = UpgradeModes[modeInt] ?: FirmwareUpgradeManager.Mode.TEST_AND_CONFIRM
105111

106112
val settings = Settings.Builder().setEstimatedSwapTime(estimatedSwapTime).build()
107113

108114
try {
109-
val images = extractImagesFrom(updateBundleUri)
115+
val images = extractImagesFrom(updateBundleUri, upgradeFileType)
110116

111117
dfuManager.setMode(upgradeMode)
112118
dfuManager.start(images, settings)

react-native-mcu-manager/android/src/main/java/uk/co/playerdata/reactnativemcumanager/ReactNativeMcuManagerModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ private val TAG = "McuManagerModule"
2020

2121
class UpdateOptions : Record {
2222
@Field val estimatedSwapTime: Int = 0
23+
@Field val upgradeFileType: Int = 0
2324
@Field val upgradeMode: Int? = null
2425
}
2526

@@ -71,7 +72,6 @@ class ReactNativeMcuManagerModule : Module() {
7172
val updateFileUri = Uri.parse(updateFileUriString)
7273

7374
val upgrade = DeviceUpgrade(
74-
id,
7575
device,
7676
context,
7777
updateFileUri,

react-native-mcu-manager/ios/DeviceUpgrade.swift

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ enum JSUpgradeMode: Int {
77
case TEST_ONLY = 3
88
}
99

10+
enum UpgradeFileType: Int {
11+
case BIN = 0
12+
case ZIP = 1
13+
}
14+
1015
class DeviceUpgrade {
1116
private let id: String
1217

@@ -39,14 +44,12 @@ class DeviceUpgrade {
3944
self.logDelegate = UpdateLogDelegate()
4045
}
4146

42-
func extractImageFrom(from url: URL) throws -> [ImageManager.Image] {
43-
switch url.pathExtension.lowercased() {
44-
case "bin":
47+
func extractImageFrom(from url: URL, upgradeFileType: UpgradeFileType) throws -> [ImageManager.Image] {
48+
switch upgradeFileType {
49+
case UpgradeFileType.BIN:
4550
return try extractImageFromBinFile(from: url)
46-
case "zip":
51+
case UpgradeFileType.ZIP:
4752
return try extractImageFromZipFile(from: url)
48-
default:
49-
throw Exception(name: "UnsupportedFileType", description: "File must be .bin or .zip")
5053
}
5154
}
5255

@@ -102,7 +105,9 @@ class DeviceUpgrade {
102105
}
103106

104107
do {
105-
let images = try extractImageFrom(from: fileUrl)
108+
let images = try extractImageFrom(
109+
from: fileUrl, upgradeFileType: UpgradeFileType(rawValue: self.options.upgradeFileType)!
110+
)
106111

107112
self.bleTransport = McuMgrBleTransport(bleUuid)
108113
self.dfuManager = FirmwareUpgradeManager(transport: self.bleTransport!, delegate: self)
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import ExpoModulesCore
22

33
struct UpdateOptions: Record {
4-
@Field var estimatedSwapTime: TimeInterval = 0
5-
@Field var upgradeMode: Int?
4+
@Field var estimatedSwapTime: TimeInterval = 0
5+
@Field var upgradeFileType: Int = 0
6+
@Field var upgradeMode: Int?
67
}

react-native-mcu-manager/src/Upgrade.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
import ReactNativeMcuManager from './ReactNativeMcuManagerModule';
22

3+
export enum UpgradeFileType {
4+
/**
5+
* A single binary update image.
6+
*/
7+
BIN = 0,
8+
9+
/**
10+
* A zip file containing a manifest.json file that describes the contents of the zip file.
11+
*/
12+
ZIP = 1,
13+
}
14+
315
export enum UpgradeMode {
416
/**
517
* This mode is the default and recommended mode for performing upgrades due to it's ability to
@@ -26,6 +38,11 @@ export interface UpgradeOptions {
2638
*/
2739
estimatedSwapTime: number;
2840

41+
/**
42+
* The type of firmware update file.
43+
*/
44+
upgradeFileType: UpgradeFileType;
45+
2946
/**
3047
* McuManager firmware upgrades can actually be performed in few different ways.
3148
* These different upgrade modes determine the commands sent after the upload step.

react-native-mcu-manager/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import McuManagerModule from './ReactNativeMcuManagerModule';
22
import type { FirmwareUpgradeState, UpgradeOptions } from './Upgrade';
3-
import Upgrade, { UpgradeMode } from './Upgrade';
3+
import Upgrade, { UpgradeMode, UpgradeFileType } from './Upgrade';
44

55
export const eraseImage = McuManagerModule?.eraseImage as (
66
bleId: string
77
) => Promise<void>;
88

9-
export { Upgrade, UpgradeMode };
9+
export { Upgrade, UpgradeMode, UpgradeFileType };
1010
export type { FirmwareUpgradeState, UpgradeOptions };

0 commit comments

Comments
 (0)