node.jsとexpressを使用して、 ZeroMQとsocket.ioを介して各ユーザーにリアルタイムのaprsストリームを提供するWebアプリケーションを作成しています。
コンセプトは次のとおりです。node.jsアプリには、ZeroMQパブリッシャーにサブスクライブすることで完全なaprsストリームが送信されます。ユーザーがWebページ(フルスクリーンマップ)にアクセスすると、socket.ioセッションが設定され、マップの現在の表示領域の境界がサーバーに返送されます。その後、サーバーは完全なフィードのスコープを設定して、マップ上にある新しいスポットのみをユーザーに送信できます。
ほとんどは正常に機能していますが、複数の人がサイトをロードすると機能しなくなります。現在表示されているマップのスコープがグローバルになり、1つのマップをズーム/パンすると、新しい場所のスポットが両方のブラウザに表示され始めます。
各socket.ioセッションは、独自のスコープを保持し、一意のスコープマップ境界からのみデータを受信し、各訪問者に一意である必要があります。socket.io接続内にコールバックをネストしようとしましzmqsocket.on "message", (data) ->
たが、それでも同じ結果が生成されます(適切なコールバック内で宣言されたmapbounds変数を使用しても)。
アプリケーションの完全なソースはここにあります:https ://github.com/gmcintire/aprs.bz
npm install
アプリをローカルでテストする場合は、リポジトリのクローンを作成し、実行しcoffee app.coffee
てから開始できるはずです。ZeroMQサーバーから完全なAPRSフィードのストリーミングを開始することに注意してください。これは約100Kバイト/秒になる可能性があります。
app.coffee
express = require("express")
routes = require("./routes")
geolib = require("geolib")
zmq = require("zmq")
zmqsocket = zmq.socket("sub")
zmqsocket.connect "tcp://stream.aprs.bz:12777"
zmqsocket.subscribe ""
app = module.exports = express.createServer()
io = require("socket.io").listen(app)
mapbounds = ""
io.sockets.on "connection", (socket) ->
#console.log socket
socket.on "mapmove", (mapcoords) ->
console.log mapbounds
mapbounds = mapcoords
zmqsocket.on "message", (data) ->
packet = JSON.parse(data)
#console.log packet
if packet.latitude? and packet.longitude? and (mapbounds != "")
insideMap = geolib.isPointInside
latitude: packet.latitude
longitude: packet.longitude
, [
latitude: mapbounds._northEast.lat
longitude: mapbounds._southWest.lng
,
latitude: mapbounds._northEast.lat
longitude: mapbounds._northEast.lng
,
latitude: mapbounds._southWest.lat
longitude: mapbounds._northEast.lng
,
latitude: mapbounds._southWest.lat
longitude: mapbounds._southWest.lng
]
if insideMap
console.log "\n--------------------------------------------------------\n"
io.sockets.emit "packet", packet
console.log packet
app.configure ->
app.set "views", __dirname + "/views"
app.set "view engine", "jade"
app.use express.bodyParser()
app.use express.methodOverride()
app.use app.router
app.use express.static(__dirname + "/public")
app.configure "development", ->
app.use express.errorHandler(
dumpExceptions: true
showStack: true
)
app.configure "production", ->
app.use express.errorHandler()
app.get "/", routes.index
if app.settings.env == "development"
app.listen 3000
else
app.listen 80
console.log "Express server listening on port %d in %s mode", app.address().port, app.settings.env