3

I want to send a POST request to a camera and receive a motionJPEG stream back. I am using the Dart http package. As far as I can tell, I cannot use http.post to receive a stream as the response. I am trying to use http.Client.send. I do not know how to create a proper body and header for the http.Request.

Most IP cameras use a GET to access the MotionJPEG byte stream. However, the camera I am using is a RICOH THETA camera and it requires a POST command with a payload to be sent to the camera. If anyone knows how I can create a proper POST Request to return a stream with header and body using the dart http module, please help.

import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';

main() async {
  Uri url = Uri.parse('https://192.168.1.1/osc/commands/execute');
  var request = http.Request('POST', url);

  Map<String, String> bodyMap = {'name': 'camera.getLivePreview'};
  request.body = jsonEncode(bodyMap);

  Map<String, String> headers = {"Content-type": "application/json"};
  http.Client client = http.Client();
  StreamSubscription videoStream;
  client.head(url, headers: headers);
  client.send(request).then((response) {
    var startIndex = -1;
    var endIndex = -1;
    List<int> buf = List<int>();
    videoStream = response.stream.listen((List<int> data) {
      for (var i = 0; i < data.length; i++) {
        print(data[i]);
      }
    });
  });
}
codetricity
  • 113
  • 1
  • 1
  • 8

2 Answers2

3

I faced the same problem, what you are doing is actually correct but HTTP package modifies your request and adds some extra details to it, so rather use dart:io HttpClient.

Sample Code

import 'dart:convert';
import 'dart:io';
import 'dart:async';

main() async {
   String url =
  'https://pae.ipportalegre.pt/testes2/wsjson/api/app/ws-authenticate';
  Map map = {
       'data': {'apikey': '12345678901234567890'},
  };

  print(await apiRequest(url, map));
 }

 Future<String> apiRequest(String url, Map jsonMap) async {
     HttpClient httpClient = new HttpClient();
     HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));
     request.headers.set('content-type', 'application/json');
     request.add(utf8.encode(json.encode(jsonMap)));
     HttpClientResponse response = await request.close();
  // todo - you should check the response.statusCode
     String reply = await response.transform(utf8.decoder).join();
     httpClient.close();
     return reply;
 }

For more clarity head over to this stackoverflow post

Pratyush Tiwari
  • 451
  • 3
  • 6
  • Thanks. I was able to get it working with this tip. Too bad about the http package in dart having some issues. – codetricity Aug 01 '20 at 14:28
  • Would you please elaborate on the statement "HTTP package modifies your request and adds some extra details to it"? Thank you. – Chuck Batson Aug 23 '22 at 15:58
0

This is the snippet of how to send a post and receive a stream back. In my case, I'm getting a video stream back and extract the frames. In the snippet, I'm extracting 10 frames for testing.

It still might be possible to use the dart http module, but I haven't figured out a way. Using HttpClient works for me and is roughly the same for ease of use.

import 'dart:async';
import 'dart:io';
import 'dart:convert';

Uri apiUrl = Uri.parse('http://192.168.1.1/osc/commands/execute');

Map payload = {'name': 'camera.getLivePreview'};

void main() async {
  var client = HttpClient();
  StreamSubscription videoStream;

  var request = await client.postUrl(apiUrl)
    ..headers.contentType = ContentType.json
    ..write(jsonEncode(payload));

  HttpClientResponse response = await request.close();

  var startIndex = -1;
  var endIndex = -1;

  // frame buffer for a single frame
  List<int> buf = List<int>();
  int counter = 0;

  Duration ts = null;
  Stopwatch timer = Stopwatch();

  timer.start();

// set up list of frames
  var frameList = [];
  for (int frameCount = 0; frameCount < 10; frameCount++) {
    frameList.add(await new File('frame$frameCount.jpg'));
  }

  //  Handle the response
  var resStream = response.listen(
    (List<int> data) {
      for (var i = 0; i < data.length - 1; i++) {
        if (data[i] == 0xff && data[i + 1] == 0xd8) {
          startIndex = buf.length + i;
        }
        if (data[i] == 0xff && data[i + 1] == 0xd9) {
          endIndex = buf.length + i;
        }
      }
      buf.addAll(data);


codetricity
  • 113
  • 1
  • 1
  • 8