Hur gör jag för att "lyssna" på json ?

Permalänk

Hur gör jag för att "lyssna" på json ?

Jag har en kameramjukvara som kan skicka json via http post vid olika händelser. Hur gör jag lättast för att sätta upp en enkel server eller liknande som tar imot dessa json och där jag har möjlighet att se exakt hur dessa json ser uta samt kan "decoda" dess data så att värdet från "in:4" eller "out:2" sparas i olika variabler.

Om möjligt så skulle jag även vilja få till det så att programmet/servern lyssnar på en portrange typ mellan 25000-25010 så jag kan avgöra från vilket program det är skickat ifrån genom att se vilken port som användes.

Allt detta är helt nytt för mig som troligen är tydligt pga mina formuleringar. Jag kollade lite på nodejs och det verkar ju kunna användas tror jag men jag har aldrig använt mig av nodejs så jag förstår inte riktigt hur jag ska gå tillväga.

Permalänk
Medlem

en kompakt webbserver (typ nginx) med php som har inbyggd json_decode()-funktion lär väl vara en av de enklare vägarna, då det finns gott om support kring php på nätet.

edit: nodejs är också ett alternativ, lite mer modernt också. Men egentligen kan du skriva en liten app i valfritt språk, nästan alla har färdiga bibliotek för att decoda json, och ta emot http-anslutningar.

Permalänk
Inaktiv

@burton666: Det du söker är att bygga ett REST API. Det går som tidigare post sa att göra i de flesta språk, jag har själv bara använt asp.net web API, vilket kanske är lite overkill i det här fallet. Vill du även lagra datat i en databas?

Enklast är förmodligen att lägga upp en liten nodejs som lyssnar på den porten du vill, det finns riktigt bra tutorials ute om du googlar typ nodejs rest api, t ex denna som dock lagrar datat i en databas(mongodb). En bra start i vilket fall:

https://www.codementor.io/olatundegaruba/nodejs-restful-apis-...

Postman är grymt för att testa.

Permalänk
Hedersmedlem

Med Python och Flask:

#!/usr/bin/env python3 """Minimal Flask app to read and log JSON POST requests.""" from flask import Flask, request PORT = 25000 app = Flask(__name__) @app.route('/', methods=['POST']) def read_json(): """Read JSON from POST, log it and return "Request OK" if JSON is valid.""" data = request.get_json() print('Received JSON data:', data) return 'Request OK' if __name__ == '__main__': app.run(port=PORT)

Körs detta skript så sätts en server upp på port 25000 som tar emot JSON-data över POST. Ovan är en enda "endpoint" definierad, som tar emot JSON, skriver ut innehållet till skärmen och returnerar strängen "Request OK".

Om du vill att en och samma server ska lyssna på mer än en port så pratar vi sannolikt en reverse proxy som tar emot dessa anrop och vidarebefordrar dem till en och samma interna server.

Visa signatur

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.

Permalänk
Medlem

Om du inte vill sätta upp en server eller dylikt så har jag ett färdig REST API inbyggt i Excel med färdig kod för att hantera både POST och GET. Klarar självklart även av att parsa JSON också. Skicka PM vid intresse.

Visa signatur

Citera så jag hittar tillbaka...

1: AM4 3600X, RTX 4060 OC, X570-I, 32GB 3200MHz, SF450, 34”
2: AM4 3600, RTX 3070 OC, B550-I, 16GB 3600MHz, SF750, 34”
3: AM4 3600, RTX 3070 OC, B550-I, 16GB 3200MHz, SF600, 34”

Permalänk
Medlem

För att lyssna på flera portar med NodeJS kan du skapa en array bara som innehåller port-rangen, sedan startar du en server för varje värde i arrayen.

Inte testat, men ungefär i den här stilen:

const ports = [...Array(11).keys()].map(i => 25000 + i) ports.forEach((port) => { http.createServer((req, res) => { // vad som exekveras efter den skapats }).listen(port); });

Vill man undvika magiska siffror, så kan du ju skapa en konstant för startporten och så vidare också. Detta är bara ett exempel.

Sedan skulle du kunna deploya på Heroku eller något.

Permalänk
Medlem
Skrivet av anon237522:

@burton666: Det du söker är att bygga ett REST API. Det går som tidigare post sa att göra i de flesta språk, jag har själv bara använt asp.net web API, vilket kanske är lite overkill i det här fallet. Vill du även lagra datat i en databas?

Postman är grymt för att testa.

Det går relativt enkelt att få till i ASP.net, och även bygga som en standalone applikation som inte kräver IIS.

VisualStudio Community edition är helt gratis och sedan VS2017 så är det relativt litet och tar bara några minuter att installera om man har bra bandbredd.

Tanka ner VS community installern från visualstudio.com och klicka i ASP.net and web development.

Starta VS och skapa ett nytt projekt:
File->New Project->Templates->Visual C#->Web->Asp.NET Core Web Application (.NET Framework).

Döp det till JsonListener, välj Web API och OK.

Byt ut koden i Program.cs

using System.IO; using System.Linq; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; namespace JsonListener { public class Program { public static void Main(string[] args) { var urls = Enumerable.Range(25000, 11) .Select(port => $"http://localhost:{port}") .ToArray(); var host = new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .UseUrls(urls) .Build(); host.Run(); } } }

Byt ut koden i ValuesController.cs:

using System; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; namespace JsonListener.Controllers { [Route("")] public class ValuesController : Controller { private readonly ILogger _logger; public ValuesController(ILogger<ValuesController> logger) { _logger = logger; } [HttpPost] public void Post([FromBody]JToken json) { _logger.LogInformation($"Mottog json på port {Request.Host.Port}:{Environment.NewLine}{json}"); switch (Request.Host.Port) { case 25000: var inValue = json["in"].Value<int>(); var outValue = json["out"].Value<int>(); break; case 25001: var isChoklad = json["glass"]["choklad"].Value<bool>(); break; default: break; } } } }

Klart.

På knappen för att starta applikationen i Visual Studio kan du välja i dropdownen om du vill hosta i IIS Express som följer med visual studio, eller som en standalone .exe.

Båda går att debugga, du kan sätta en brytpunk i ValueControllerns postmetod för att debugga när du får ett anrop.

Du kan testa anropa med Postman om du laddar ner det från getpostman.com

Välj Post, url: http://localhost:25001/
Under Body, välj Raw och längst till höger JSON (application/json)

{ "glass": { "choklad": true, "jordgubb": true } }

När du slutligen är helt klar med din webserverapp kan du i VS även publicera den till en Folder från buildmenyn.

Permalänk
Skrivet av phz:

Med Python och Flask:

#!/usr/bin/env python3 """Minimal Flask app to read and log JSON POST requests.""" from flask import Flask, request PORT = 25000 app = Flask(__name__) @app.route('/', methods=['POST']) def read_json(): """Read JSON from POST, log it and return "Request OK" if JSON is valid.""" data = request.get_json() print('Received JSON data:', data) return 'Request OK' if __name__ == '__main__': app.run(port=PORT)

Körs detta skript så sätts en server upp på port 25000 som tar emot JSON-data över POST. Ovan är en enda "endpoint" definierad, som tar emot JSON, skriver ut innehållet till skärmen och returnerar strängen "Request OK".

Om du vill att en och samma server ska lyssna på mer än en port så pratar vi sannolikt en reverse proxy som tar emot dessa anrop och vidarebefordrar dem till en och samma interna server.

När jag kör koden så verkar det som att jag bara kan "trigga" servern från samma maskin. Hur gör jag så att jag kan skicka json posts från någon annan maskin på samma nätverk?

Permalänk
Medlem
Skrivet av burton666:

När jag kör koden så verkar det som att jag bara kan "trigga" servern från samma maskin. Hur gör jag så att jag kan skicka json posts från någon annan maskin på samma nätverk?

Flasks dev-server lyssnar på localhost by default (dvs, 127.0.0.1). Ställ in den på att lyssna på allt istället (dvs, 0.0.0.0), eller på host-maskinens lokala IP-address (bör vara någonting i stil med 192.168.1.x). Du behöver modifiera koden som @phz skrev med följande:

[ ... CODE OMITTED ... ] PORT = 25000 HOST = '0.0.0.0' [ ... CODE OMITTED ... ] if __name__ == '__main__': app.run(port=PORT, host=HOST)

Också viktigt att det inte ligger någon brandvägg i vägen.

Notera även att Flasks inbyggda server är just en dev-server, den är inte till för att köras i produktion (långsam, servar bara en request i taget etc). Den räcker nog för dina ändamål ändå eftersom det bara är du som ska använda appen, men om du märker av att det går riktigt segt vill du nog sätta upp en ordentlig server. Alternativ kan du läsa om här: Deployment Options - Flask Docs.

Permalänk

@SimpLar:

Nu känner jag att jag är ute på riktigt tunn is då mina kunskaper är minimala inom detta området. Men jag fick det här svaret när jag ställde en fråga till utvecklaren av ett program som jag vill kunna använda. Är detta något som är relativt lätt att åstadkomma? Och hur gör jag det isåfall?

"I'd suggest using API like this:
- start a background worker on your flask server and in infinite cycle make requests to Camlytics API (like in the example http://camlytics.com/help/api.html)
- when there are no events, request is terminated by timeout, can send another request
"

Permalänk
Medlem

@burton666: Får en 404 på den där länken, men tar man bort http så hittar man en minimal dokumentationssida för ett REST api, är det korrekt?

Jag är osäker på vad utvecklaren syftar på med "background worker on flask server". Antingen så menar han en ny tråd, eller så menar han en faktisk, parallell background worker. I det senare fallet måste man man använda en s.k. Task Queue (e.g. Celery) som kan köra workers i bakgrunden, men man behöver även en message broker (e.g. redis), och det känns rätt bajsnödigt för att polla ett api.

Jag är lite osäker på exakt vad det är du vill göra. Vill du bara ha ett program som pollar det där REST-apit och skickar notifikationer (någonstans) när det får ett svar så behöver du inte Flask, du kan skriva det i "vanlig" Python, och relativt enkelt. Kan du försöka förklara för mig exakt vad det är du vill göra så kanske jag kan hjälpa dig bättre?

Permalänk

@SimpLar:
Ok, jag vill helt enkelt få en notifikation när något händer i programmet. Typ att när något kommer in i bild på en kamera så skall ett http post triggas så att jag kan få något att reagera på detta.
Som jag fattade det så skickar inte programmet ut något utan måste pollas manuellt för att se om/vilka events som har triggats. Men jag kan ha fel.

Permalänk
Medlem

@burton666
Ok, men då låter det inte som att du behöver ett användargränssnitt alls, än mindre ett på webben, så jag ser ingen anledning att använda Flask. Du behöver överhuvudtaget inte någon server, utan bara ett litet script som med jämna mellanrum pollar APIn och skickar notifikationer (via ex. e-mail, sms, POST till att annat API) varje gång den får ett icke-tomt JSON-objekt som svar. Vilket iofs KAN ses som en server men jag skulle själv inte kalla det så.

Låter det som lösningen du är ute efter?

Skickades från m.sweclockers.com