Add Info-Beamer API endpoints and update node.lua for streaming channels
This commit is contained in:
0
INTEGRATION.md
Normal file
0
INTEGRATION.md
Normal file
0
INTEGRATION_GUIDE.md
Normal file
0
INTEGRATION_GUIDE.md
Normal file
6
config.json
Normal file
6
config.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"server_url": "http://192.168.1.22",
|
||||||
|
"player_id": "REPLACE_WITH_YOUR_DEVICE_ID",
|
||||||
|
"refresh_interval": 30,
|
||||||
|
"default_duration": 10
|
||||||
|
}
|
||||||
46
node.lua
46
node.lua
@@ -1,46 +1,47 @@
|
|||||||
-- Info-Beamer script with scheduling support
|
-- Info-Beamer script with streaming channel support
|
||||||
gl.setup(NATIVE_WIDTH, NATIVE_HEIGHT)
|
gl.setup(NATIVE_WIDTH, NATIVE_HEIGHT)
|
||||||
|
|
||||||
local json = require "json"
|
local json = require "json"
|
||||||
local font = resource.load_font "roboto.ttf"
|
local font = resource.load_font "roboto.ttf"
|
||||||
|
|
||||||
local server_url = CONFIG.server_url or "http://localhost:5000"
|
local server_url = CONFIG.server_url or "http://192.168.1.22"
|
||||||
local refresh_interval = CONFIG.refresh_interval or 60
|
local player_id = CONFIG.player_id or "default_player"
|
||||||
|
local refresh_interval = CONFIG.refresh_interval or 30
|
||||||
local default_duration = CONFIG.default_duration or 10
|
local default_duration = CONFIG.default_duration or 10
|
||||||
|
|
||||||
local playlist = {}
|
local playlist = {}
|
||||||
local current_item = 1
|
local current_item = 1
|
||||||
local item_start_time = 0
|
local item_start_time = 0
|
||||||
local last_update = 0
|
local last_update = 0
|
||||||
local schedule_info = {}
|
local channel_info = {}
|
||||||
|
|
||||||
function update_playlist()
|
function update_playlist()
|
||||||
-- Fetch scheduled playlist from server
|
-- Fetch channel content from server
|
||||||
local url = server_url .. "/api/playlist"
|
local url = server_url .. "/api/player/" .. player_id .. "/content"
|
||||||
util.post_and_wait(url, "", function(response)
|
util.post_and_wait(url, "", function(response)
|
||||||
if response.success then
|
if response.success then
|
||||||
local data = json.decode(response.content)
|
local data = json.decode(response.content)
|
||||||
if data and data.items then
|
if data and data.content then
|
||||||
playlist = data.items
|
playlist = data.content
|
||||||
print("Updated playlist: " .. #playlist .. " items")
|
print("Updated channel content: " .. #playlist .. " items")
|
||||||
|
|
||||||
-- Load assets
|
-- Load assets
|
||||||
for i, item in ipairs(playlist) do
|
for i, item in ipairs(playlist) do
|
||||||
if item.type == "image" then
|
if item.type == "image" then
|
||||||
item.resource = resource.load_image(server_url .. "/uploads/" .. item.asset)
|
item.resource = resource.load_image(server_url .. "/uploads/" .. item.filename)
|
||||||
elseif item.type == "video" then
|
elseif item.type == "video" then
|
||||||
item.resource = resource.load_video(server_url .. "/uploads/" .. item.asset)
|
item.resource = resource.load_video(server_url .. "/uploads/" .. item.filename)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Also fetch schedule information
|
-- Also fetch channel information
|
||||||
local schedule_url = server_url .. "/api/schedule"
|
local channel_url = server_url .. "/api/player/" .. player_id .. "/channel"
|
||||||
util.post_and_wait(schedule_url, "", function(response)
|
util.post_and_wait(channel_url, "", function(response)
|
||||||
if response.success then
|
if response.success then
|
||||||
schedule_info = json.decode(response.content) or {}
|
channel_info = json.decode(response.content) or {}
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -55,8 +56,9 @@ function node.render()
|
|||||||
|
|
||||||
-- If no playlist items, show waiting message
|
-- If no playlist items, show waiting message
|
||||||
if #playlist == 0 then
|
if #playlist == 0 then
|
||||||
font:write(100, 100, "Waiting for scheduled content...", 50, 1, 1, 1, 1)
|
font:write(100, 100, "Waiting for channel content...", 50, 1, 1, 1, 1)
|
||||||
font:write(100, 200, "Server: " .. server_url, 30, 0.7, 0.7, 0.7, 1)
|
font:write(100, 200, "Server: " .. server_url, 30, 0.7, 0.7, 0.7, 1)
|
||||||
|
font:write(100, 250, "Player ID: " .. player_id, 30, 0.7, 0.7, 0.7, 1)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -87,17 +89,17 @@ function node.render()
|
|||||||
item.resource:draw(0, 0, WIDTH, HEIGHT)
|
item.resource:draw(0, 0, WIDTH, HEIGHT)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Show schedule info overlay (optional)
|
-- Show channel info overlay (optional)
|
||||||
if item.schedule_name then
|
if channel_info.name then
|
||||||
font:write(10, HEIGHT - 60, "Schedule: " .. item.schedule_name, 20, 1, 1, 1, 0.8)
|
font:write(10, HEIGHT - 60, "Channel: " .. channel_info.name, 20, 1, 1, 1, 0.8)
|
||||||
if item.priority then
|
if channel_info.description then
|
||||||
font:write(10, HEIGHT - 30, "Priority: " .. item.priority, 20, 1, 1, 1, 0.8)
|
font:write(10, HEIGHT - 30, channel_info.description, 20, 1, 1, 1, 0.8)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Show current time
|
-- Show current time
|
||||||
local current_time = schedule_info.current_time or "00:00"
|
local current_time = os.date("%H:%M")
|
||||||
font:write(WIDTH - 100, 20, current_time, 24, 1, 1, 1, 0.9)
|
font:write(WIDTH - 100, 20, current_time, 24, 1, 1, 1, 0.9)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
59
server.py
59
server.py
@@ -552,6 +552,65 @@ def init_db():
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
print("Created default streaming channel")
|
print("Created default streaming channel")
|
||||||
|
|
||||||
|
# API Endpoints for Info-Beamer Integration
|
||||||
|
@app.route('/api/player/<device_id>/content')
|
||||||
|
def api_player_content(device_id):
|
||||||
|
"""Get content for a specific player"""
|
||||||
|
player = Player.query.filter_by(device_id=device_id).first()
|
||||||
|
if not player:
|
||||||
|
return jsonify({'error': 'Player not found'}), 404
|
||||||
|
|
||||||
|
if not player.channel_id:
|
||||||
|
return jsonify({'content': []})
|
||||||
|
|
||||||
|
# Get content from the player's assigned channel
|
||||||
|
channel_content = ChannelContent.query.filter_by(channel_id=player.channel_id).order_by(ChannelContent.order).all()
|
||||||
|
|
||||||
|
content_list = []
|
||||||
|
for content in channel_content:
|
||||||
|
media_file = MediaFile.query.get(content.media_file_id)
|
||||||
|
if media_file:
|
||||||
|
content_list.append({
|
||||||
|
'filename': media_file.filename,
|
||||||
|
'type': 'image' if media_file.file_type.startswith('image/') else 'video',
|
||||||
|
'duration': content.duration or 10,
|
||||||
|
'order': content.order
|
||||||
|
})
|
||||||
|
|
||||||
|
return jsonify({'content': content_list})
|
||||||
|
|
||||||
|
@app.route('/api/player/<device_id>/channel')
|
||||||
|
def api_player_channel(device_id):
|
||||||
|
"""Get channel information for a specific player"""
|
||||||
|
player = Player.query.filter_by(device_id=device_id).first()
|
||||||
|
if not player:
|
||||||
|
return jsonify({'error': 'Player not found'}), 404
|
||||||
|
|
||||||
|
if not player.channel_id:
|
||||||
|
return jsonify({'name': 'No Channel Assigned', 'description': 'No channel assigned to this player'})
|
||||||
|
|
||||||
|
channel = StreamingChannel.query.get(player.channel_id)
|
||||||
|
if not channel:
|
||||||
|
return jsonify({'error': 'Channel not found'}), 404
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'name': channel.name,
|
||||||
|
'description': channel.description,
|
||||||
|
'is_active': channel.is_active
|
||||||
|
})
|
||||||
|
|
||||||
|
@app.route('/api/player/<device_id>/heartbeat', methods=['POST'])
|
||||||
|
def api_player_heartbeat(device_id):
|
||||||
|
"""Update player last seen timestamp"""
|
||||||
|
player = Player.query.filter_by(device_id=device_id).first()
|
||||||
|
if not player:
|
||||||
|
return jsonify({'error': 'Player not found'}), 404
|
||||||
|
|
||||||
|
player.last_seen = datetime.utcnow()
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return jsonify({'status': 'ok'})
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
init_db()
|
init_db()
|
||||||
app.run(host='0.0.0.0', port=80, debug=True)
|
app.run(host='0.0.0.0', port=80, debug=True)
|
||||||
Reference in New Issue
Block a user