diff --git a/pkg/webui/console/views/device-general-settings/index.js b/pkg/webui/console/views/device-general-settings/index.js index a34ed6d021..8e6c895c45 100644 --- a/pkg/webui/console/views/device-general-settings/index.js +++ b/pkg/webui/console/views/device-general-settings/index.js @@ -36,7 +36,6 @@ import { selectNsConfig, } from '@ttn-lw/lib/selectors/env' -import { hexToBase64 } from '@console/lib/bytes' import { mayEditApplicationDeviceKeys, mayReadApplicationDeviceKeys, @@ -101,9 +100,7 @@ const DeviceGeneralSettings = () => { const { ids: { dev_eui: devEui, join_eui: joinEui }, } = device - await dispatch( - attachPromise(unclaimDevice(appId, devId, hexToBase64(devEui), hexToBase64(joinEui))), - ) + await dispatch(attachPromise(unclaimDevice(appId, devId, devEui, joinEui))) }, [appId, devId, device, dispatch]) const handleUnclaimFailure = useCallback(async () => { diff --git a/sdk/js/src/service/claim.js b/sdk/js/src/service/claim.js index 2340ac9cd6..b1894cdb3e 100644 --- a/sdk/js/src/service/claim.js +++ b/sdk/js/src/service/claim.js @@ -14,6 +14,7 @@ import autoBind from 'auto-bind' +import hexToBase64 from '../util/bytes' import Marshaler from '../util/marshaler' class DeviceClaim { @@ -62,8 +63,8 @@ class DeviceClaim { } const response = await this._api.EndDeviceClaimingServer.Unclaim(params, { - dev_eui: devEui, - join_eui: joinEui, + dev_eui: hexToBase64(devEui), + join_eui: hexToBase64(joinEui), }) return Marshaler.payloadSingleResponse(response) diff --git a/sdk/js/src/util/bytes.js b/sdk/js/src/util/bytes.js new file mode 100644 index 0000000000..411c485400 --- /dev/null +++ b/sdk/js/src/util/bytes.js @@ -0,0 +1,46 @@ +// Copyright © 2023 The Things Network Foundation, The Things Industries B.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * Converts hex encoded string to base64. + * + * @param {string} str - Hex encoded string. + * @returns {string} - `str` base64 encoded. + */ +export const hexToBase64 = str => + btoa( + String.fromCharCode.apply( + null, + str + .replace(/\r|\n/g, '') + .replace(/([\da-fA-F]{2}) ?/g, '0x$1 ') + .replace(/ +$/, '') + .split(' '), + ), + ) + +/** + * Converts base64 encoded string to hex. + * + * @param {string} str - Base64 encoded string. + * @returns {string} - `str` hex encoded. + */ +export const base64ToHex = str => + Array.from(atob(str.replace(/[ \r\n]+$/, ''))) + .map(char => { + const tmp = char.charCodeAt(0).toString(16) + + return tmp.length > 1 ? tmp : `0${tmp}` + }) + .join('')