Skip to content

Commit 16878e9

Browse files
authored
Merge pull request #80 from usetrmnl/76-byos_hanami-compatibility
[ADDED] BYOS Hanami server compatibility
2 parents f4d0f4f + 29ebb8a commit 16878e9

File tree

10 files changed

+494
-34
lines changed

10 files changed

+494
-34
lines changed

app/src/main/java/ink/trmnl/android/data/TrmnlDeviceConfigDataStore.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class TrmnlDeviceConfigDataStore
5252
private val API_BASE_URL_KEY = stringPreferencesKey("api_base_url")
5353
private val REFRESH_RATE_SEC_KEY = longPreferencesKey("refresh_rate_seconds")
5454
private val CONFIG_JSON_KEY = stringPreferencesKey("config_json")
55+
private val DEVICE_MAC_ID_KEY = stringPreferencesKey("device_mac_id")
5556
}
5657

5758
private val deviceTypeAdapter = moshi.adapter(TrmnlDeviceType::class.java)
@@ -96,6 +97,14 @@ class TrmnlDeviceConfigDataStore
9697
preferences[REFRESH_RATE_SEC_KEY]
9798
}
9899

100+
/**
101+
* Gets the device MAC address as a Flow
102+
*/
103+
val deviceMacIdFlow: Flow<String?> =
104+
context.deviceConfigStore.data.map { preferences ->
105+
preferences[DEVICE_MAC_ID_KEY]
106+
}
107+
99108
/**
100109
* Gets the complete device config as a Flow
101110
*/
@@ -123,12 +132,14 @@ class TrmnlDeviceConfigDataStore
123132
val token = preferences[ACCESS_TOKEN_KEY]
124133
val url = preferences[API_BASE_URL_KEY] ?: TRMNL_API_SERVER_BASE_URL
125134
val refreshRate = preferences[REFRESH_RATE_SEC_KEY] ?: DEFAULT_REFRESH_INTERVAL_SEC
135+
val deviceMacId = preferences[DEVICE_MAC_ID_KEY]
126136

127137
if (token != null) {
128138
TrmnlDeviceConfig(
129139
type = type,
130140
apiBaseUrl = url,
131141
apiAccessToken = token,
142+
deviceMacId = deviceMacId,
132143
refreshRateSecs = refreshRate,
133144
)
134145
} else {
@@ -152,6 +163,11 @@ class TrmnlDeviceConfigDataStore
152163
preferences[ACCESS_TOKEN_KEY] = config.apiAccessToken
153164
preferences[API_BASE_URL_KEY] = config.apiBaseUrl
154165
preferences[REFRESH_RATE_SEC_KEY] = config.refreshRateSecs
166+
167+
// Save device ID if available
168+
config.deviceMacId?.let { deviceMacId ->
169+
preferences[DEVICE_MAC_ID_KEY] = deviceMacId
170+
}
155171
}
156172
} catch (e: Exception) {
157173
Timber.tag(TAG).e(e, "Failed to save device config")
@@ -194,6 +210,19 @@ class TrmnlDeviceConfigDataStore
194210
}
195211
}
196212

213+
/**
214+
* Saves the device ID (MAC address)
215+
*/
216+
suspend fun saveDeviceMacId(deviceMacId: String?) {
217+
context.deviceConfigStore.edit { preferences ->
218+
if (deviceMacId != null) {
219+
preferences[DEVICE_MAC_ID_KEY] = deviceMacId
220+
} else {
221+
preferences.remove(DEVICE_MAC_ID_KEY)
222+
}
223+
}
224+
}
225+
197226
/**
198227
* Checks if a token is already set
199228
*/

app/src/main/java/ink/trmnl/android/data/TrmnlDisplayRepository.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ class TrmnlDisplayRepository
5353
.getNextDisplayData(
5454
fullApiUrl = constructApiUrl(trmnlDeviceConfig.apiBaseUrl, NEXT_PLAYLIST_SCREEN_API_PATH),
5555
accessToken = trmnlDeviceConfig.apiAccessToken,
56+
// Send device MAC ID if available (used for BYOS service)
57+
deviceMacId = trmnlDeviceConfig.deviceMacId,
58+
// TEMP FIX: Use Base64 encoding to avoid relative path issue
59+
// See https://github.com/usetrmnl/trmnl-android/issues/76#issuecomment-2980018109
60+
useBase64 = trmnlDeviceConfig.type == TrmnlDeviceType.BYOS,
5661
)
5762

5863
when (result) {

app/src/main/java/ink/trmnl/android/model/TrmnlDeviceConfig.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,9 @@ data class TrmnlDeviceConfig constructor(
1919
val type: TrmnlDeviceType,
2020
val apiBaseUrl: String,
2121
val apiAccessToken: String,
22+
/**
23+
* Device MAC address for API authentication, usually used by BYOS servers.
24+
*/
25+
val deviceMacId: String? = null,
2226
val refreshRateSecs: Long = DEFAULT_REFRESH_INTERVAL_SEC,
2327
)

app/src/main/java/ink/trmnl/android/network/TrmnlApiService.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,19 @@ interface TrmnlApiService {
4141
*
4242
* NOTE: This API always loads the next plugin image from the playlist.
4343
*
44+
* @param fullApiUrl The complete API URL to call
45+
* @param accessToken The device's API key (required)
46+
* @param deviceMacId The device's MAC address (optional)
47+
* @param useBase64 Whether to request Base64-encoded image data (optional)
48+
*
4449
* @see getCurrentDisplayData
4550
*/
4651
@GET
4752
suspend fun getNextDisplayData(
4853
@Url fullApiUrl: String,
4954
@Header("access-token") accessToken: String,
55+
@Header("ID") deviceMacId: String? = null,
56+
@Header("BASE64") useBase64: Boolean? = null,
5057
): ApiResult<TrmnlDisplayResponse, Unit>
5158

5259
/**

app/src/main/java/ink/trmnl/android/network/model/TrmnlDisplayResponse.kt

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package ink.trmnl.android.network.model
22

33
import com.squareup.moshi.Json
44
import com.squareup.moshi.JsonClass
5+
import ink.trmnl.android.util.HTTP_NONE
56

67
/**
78
* Data class representing the response from the TRMNL API for display data.
@@ -34,10 +35,34 @@ import com.squareup.moshi.JsonClass
3435
* ```json
3536
* {"status":500,"error":"Device not found","reset_firmware":true}
3637
* ```
38+
*
39+
* Sample response from BYOS Hanami server:
40+
* ```json
41+
* {
42+
* "filename": "demo.bmp",
43+
* "firmware_url": "http://localhost:2443/assets/firmware/1.4.8.bin",
44+
* "image_url": "https://localhost:2443/assets/screens/A1B2C3D4E5F6/demo.bmp",
45+
* "image_url_timeout": 0,
46+
* "refresh_rate": 130,
47+
* "reset_firmware": false,
48+
* "special_function": "sleep",
49+
* "update_firmware": false
50+
* }
51+
* ```
3752
*/
3853
@JsonClass(generateAdapter = true)
3954
data class TrmnlDisplayResponse(
40-
val status: Int,
55+
/**
56+
* Status code indicating the result of the request.
57+
* - 0: Success
58+
* - 500: Error (e.g., device not found)
59+
*
60+
* Also on `byos_hanami`, the status code is not provided.
61+
* See
62+
* - https://github.com/usetrmnl/byos_hanami?tab=readme-ov-file#apis
63+
* - https://discord.com/channels/1281055965508141100/1331360842809348106/1383221807716237433
64+
*/
65+
val status: Int = HTTP_NONE,
4166
@Json(name = "image_url") val imageUrl: String?,
4267
@Json(name = "filename") val imageName: String?,
4368
@Json(name = "update_firmware") val updateFirmware: Boolean?,

0 commit comments

Comments
 (0)