@@ -136,6 +136,29 @@ async def choose_varied(hass, files: list[str], store_key: str = "recent_images"
136136ALLOWED_EXT = (".jpg" ,)
137137
138138
139+ def _server_timestamp () -> str :
140+ """Return the current UTC time as a Unix timestamp in seconds."""
141+ return str (int (dt .now (timezone .utc ).timestamp ()))
142+
143+
144+ def json_response_with_timestamp (
145+ data : dict ,
146+ * ,
147+ status : int = HTTPStatus .OK ,
148+ ** kwargs ,
149+ ) -> web .Response :
150+ """Create a JSON response including the BLOOMIN8 clock-sync header."""
151+ headers = dict (kwargs .pop ("headers" , {}) or {})
152+ headers ["X-Server-Timestamp" ] = _server_timestamp ()
153+
154+ return web .json_response (
155+ data ,
156+ status = status ,
157+ headers = headers ,
158+ ** kwargs ,
159+ )
160+
161+
139162class Bloomin8PullView (HomeAssistantView ):
140163 """Implements GET /eink_pull for BLOOMIN8 devices."""
141164
@@ -152,7 +175,7 @@ async def get(self, request: web.Request) -> web.Response:
152175 token = request .headers .get ("X-Access-Token" , "" )
153176 expected = self .cfg ["access_token" ]
154177 if not expected or token != expected :
155- return web . json_response (
178+ return json_response_with_timestamp (
156179 {"status" : 401 , "type" : "ERROR" , "message" : "Unauthorized" },
157180 status = HTTPStatus .UNAUTHORIZED ,
158181 )
@@ -213,7 +236,7 @@ async def get(self, request: web.Request) -> web.Response:
213236 files = []
214237
215238 if not files :
216- return web . json_response (
239+ return json_response_with_timestamp (
217240 {
218241 "status" : 204 ,
219242 "message" : "No image available" ,
@@ -253,7 +276,7 @@ async def get(self, request: web.Request) -> web.Response:
253276 )
254277 except Exception as err :
255278 _LOGGER .exception ("Failed to publish image %s -> %s: %s" , src_path , dst_path , err )
256- return web . json_response (
279+ return json_response_with_timestamp (
257280 {"status" : 500 , "type" : "ERROR" , "message" : "Failed to publish image" },
258281 status = HTTPStatus .INTERNAL_SERVER_ERROR ,
259282 )
@@ -283,7 +306,7 @@ async def get(self, request: web.Request) -> web.Response:
283306 except Exception :
284307 pass
285308
286- return web . json_response (
309+ return json_response_with_timestamp (
287310 {
288311 "status" : 200 ,
289312 "type" : "SHOW" ,
@@ -312,7 +335,7 @@ async def get(self, request: web.Request) -> web.Response:
312335 token = request .headers .get ("X-Access-Token" , "" )
313336 expected = self .cfg ["access_token" ]
314337 if not expected or token != expected :
315- return web . json_response (
338+ return json_response_with_timestamp (
316339 {"status" : 401 , "type" : "ERROR" , "message" : "Unauthorized" },
317340 status = HTTPStatus .UNAUTHORIZED ,
318341 )
@@ -352,7 +375,7 @@ async def get(self, request: web.Request) -> web.Response:
352375 pull_id , success , request .remote
353376 )
354377
355- return web . json_response (
378+ return json_response_with_timestamp (
356379 {
357380 "status" : 200 ,
358381 "message" : "Feedback recorded"
0 commit comments