Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@andrieslouw
Created August 14, 2021 13:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrieslouw/a79c11b9827f501e37775b430fa1315e to your computer and use it in GitHub Desktop.
Save andrieslouw/a79c11b9827f501e37775b430fa1315e to your computer and use it in GitHub Desktop.
Sony RX0 II camera read
using System;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Timers;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;
using System.Diagnostics;
using Serilog;
/*
Example:
Camera myCamera = new Camera();
myCamera.CameraPowerOnProcedure();
App.myCamera.StartRecording();
myCamera.StopRecording();
await myCamera.CameraTurnOffAsync();
*/
namespace VideoBooth
{
public class Camera
{
private String cid = "";
private String bid = "";
private String modelName = "";
private String serialNumber = "";
private String browserKey = "";
private Uri baseAddress;
private static System.Timers.Timer aTimer;
private CookieContainer myCookieContainer = new CookieContainer();
private long timestampInit = 0;
public bool connectionBoxConnected = false;
public bool cameraConnected = false;
public int liveViewPortNumber = 0;
//Status
public String movieRecordingState = "";
public String recordingSettingMovie = "";
public String batteryLevelIndicator = "";
public String MediaSlot1Status = "";
public int remainingShootingTime = 0;
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
public Camera()
{
Log.Information("[Camera] constructor called");
baseAddress = new Uri("http://169.254.200.200");
// broadcast address when camera is in stand-by
cid = "169.254.200.200:-1:-1";
Log.Information("[Camera] constructor done");
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
public void PrepareState()
{
// get 169.254.200.200/
// This gets the index page which sets a cookie in the cookie container
var responseString = "";
using (var handler = new HttpClientHandler { CookieContainer = myCookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = this.baseAddress })
{
var response = client.GetAsync("").Result;
responseString = response.Content.ReadAsStringAsync().Result;
}
this.timestampInit = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
// get browser key from values.php
this.getBrowserKey().Wait(); // sets the browser key
Log.Information("Browserkey set: {0}", this.browserKey);
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
public Boolean CanRecord()
{
if (connectionBoxConnected == false)
{
Log.Information("[record check]\tNo connection box");
return false;
}
else if (cameraConnected == false)
{
Log.Information("[record check]\tNo camera");
return false;
}
else if (MediaSlot1Status == "NO CARD")
{
Log.Information("[record check]\tNo card");
return false;
}
else if (remainingShootingTime < 120)
{
Log.Information("[record check]\tShooting time returned from camera API is 0 seconds.");
return false;
}
else
{
Log.Information("[record check]\tCamera can record");
return true;
}
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
public void StopRecording()
{
this.CameraRecordStopCommand();
}
public void Focus()
{
this.StartFocus();
this.StopFocus();
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
public void StartRecording()
{
this.CheckBoxStateExtendedFormData();
this.CheckBoxStateBidsOn();
this.CameraRecordStartCommand();
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
public void TurnOff()
{
this.CameraTurnOffAsync().Wait();
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
// TODO; create int return value to indicate if camera has been found
public void CameraPowerOnProcedure()
{
Log.Information("Power on procedure:");
// TODO: Check if connection box is online
// Check if camera is attached to connection box
this.GetCam0InfoAsyncStartup().Wait();
if (cameraConnected == false)
{
Log.Information("\t[Camera] turning on");
CameraTurnOn();
Log.Information("\t[Camera] waiting 10 seconds for powering on");
Thread.Sleep(10000); // wait 10 seconds
Log.Information("\t[Camera] checking if powered on");
// Check if camera is attached to connection box
this.GetCam0InfoAsyncStartup().Wait();
// Try second time if camera still not found
if (cameraConnected == false)
{
Log.Information("\t[Camera] camera not found yet");
Log.Information("[Camera] turning on again");
CameraTurnOn();
Log.Information("[Camera] waiting 10 seconds for powering on");
Thread.Sleep(10000); // wait 10 seconds
Log.Information("[Camera] checking again if powered on");
// Check if camera is attached to connection box
this.GetCam0InfoAsyncStartup().Wait();
}
}
// Assume camera is on for now; This will be periodically be checked in timed function
this.SetTimer();
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private void SetTimer()
{
// Create a timer with a two second interval.
aTimer = new System.Timers.Timer(10_000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += this.OnTimedEvent;
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private void CheckBoxStateBidsOn()
{
var values1 = new Dictionary<string, string>
{
{ "browser_key", this.browserKey },
{ "bids_on[]", "169.254.200.200" }
};
var content1 = new FormUrlEncodedContent(values1);
//Log.Information("Sending BOX status request from browser key {0}", this.browserKey);
using (var handler = new HttpClientHandler() { CookieContainer = this.myCookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("*/*"));
client.DefaultRequestHeaders.TryAddWithoutValidation("Origin", "http://169.254.200.200");
client.DefaultRequestHeaders.TryAddWithoutValidation("Referer", "http://169.254.200.200");
client.DefaultRequestHeaders.TryAddWithoutValidation("Connection", "keep-alive");
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");
HttpResponseMessage response;
string responseString = "";
try
{
response = client.PostAsync("/api.php?v=2&action=check_box_state", content1).Result;
responseString = response.Content.ReadAsStringAsync().Result;
}
catch (Exception e)
{
Log.Information(e.ToString());
}
Log.Information(responseString);
}
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private void CheckBoxStateExtendedFormData()
{
var values1 = new Dictionary<string, string>
{
{ "browser_key", this.browserKey },
{ "bids_off[]", "169.254.200.200" },
{ "master_notification", "1" },
{ "ts", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString() },
{ "sync_type", "0x01" },
};
var content1 = new FormUrlEncodedContent(values1);
//Log.Information("Sending BOX status request from browser key {0}", this.browserKey);
using (var handler = new HttpClientHandler() { CookieContainer = this.myCookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("*/*"));
client.DefaultRequestHeaders.TryAddWithoutValidation("Origin", "http://169.254.200.200");
client.DefaultRequestHeaders.TryAddWithoutValidation("Referer", "http://169.254.200.200");
client.DefaultRequestHeaders.TryAddWithoutValidation("Connection", "keep-alive");
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");
//TODO, catch exceptions (https://forums.xamarin.com/discussion/101202/try-catch-on-httpclient-not-working)
try
{
var response1 = client.PostAsync("/api.php?v=2&action=check_box_state", content1).Result;
var responseString1 = response1.Content.ReadAsStringAsync().Result;
//Log.Information(responseString1);
}
catch (Exception e)
{
Log.Information(e.ToString());
}
}
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
this.UpdateCam0StatusAsync().Wait();
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private async Task UpdateCam0StatusAsync()
{
Log.Debug("[Status update] Retrieving latest status from camera... ");
var values = new Dictionary<string, string>
{
{ "v", "2" },
{ "action", "check_cam_state" },
{ "param", "1" },
{ "bid", "169.254.200.200" }
};
using (var handler = new HttpClientHandler { CookieContainer = myCookieContainer }) // TODO: test, probably this can be deleted
using (HttpClient client = new HttpClient())
{
var camStateInfo = new JObject();
//TODO, catch exceptions (https://forums.xamarin.com/discussion/101202/try-catch-on-httpclient-not-working)
try
{
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("http://169.254.200.200/api.php", content);
var responseString = await response.Content.ReadAsStringAsync();
JObject allInfo = JObject.Parse(responseString);
camStateInfo = (JObject)allInfo["cams"][0]["prop"]["state"];
if (camStateInfo.ContainsKey("Movie_Recording_State"))
movieRecordingState = camStateInfo["Movie_Recording_State"][1].ToString();
if (camStateInfo.ContainsKey("Recoding_Setting_Movie"))
recordingSettingMovie = camStateInfo["Recoding_Setting_Movie"][1].ToString();
if (camStateInfo.ContainsKey("Battery_Level_Indicator"))
batteryLevelIndicator = camStateInfo["Battery_Level_Indicator"][1].ToString();
if (camStateInfo.ContainsKey("Media_SLOT1_Status"))
MediaSlot1Status = camStateInfo["Media_SLOT1_Status"][1].ToString();
if (camStateInfo.ContainsKey("Media_SLOT1_Remaining_Shooting_Time"))
{
string remainingShootingTimeString = camStateInfo["Media_SLOT1_Remaining_Shooting_Time"][1].ToString();
remainingShootingTime = Convert.ToInt32(remainingShootingTimeString, 16);
}
connectionBoxConnected = true;
}
catch (Exception e)
{
Log.Information("[Status update]" + e);
cameraConnected = false;
//Restarting camera
Log.Information("[Status update] Trying to start camera again");
Log.Information("[Status update] Temporarily stopping timer");
aTimer.Stop();
Log.Information("[Status update] Power on procedure");
CameraPowerOnProcedure();
Log.Information("[Status update] Starting timer again");
aTimer.Start();
}
Log.Information("\t" + movieRecordingState);
}
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private void StopFocus()
{
/* On and Off command seems to be working as a toggle switch. Turn the camera on twices, turns
the camera on and off.
*/
var values = new Dictionary<string, string>
{
{ "v", "2" },
{ "action", "cam_action" },
{ "action_name", "half_button_off_um" },
{ "cids[]", this.cid}
};
using (var handler = new HttpClientHandler { CookieContainer = myCookieContainer }) // TODO: test, probably this can be deleted
using (HttpClient client = new HttpClient())
{
var content = new FormUrlEncodedContent(values);
var response = client.PostAsync("http://169.254.200.200/api.php", content).Result;
var responseString = response.Content.ReadAsStringAsync().Result;
}
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private void StartFocus()
{
/* On and Off command seems to be working as a toggle switch. Turn the camera on twices, turns
the camera on and off.
*/
var values = new Dictionary<string, string>
{
{ "v", "2" },
{ "action", "cam_action" },
{ "action_name", "half_button_on_um" },
{ "cids[]", this.cid}
};
using (var handler = new HttpClientHandler { CookieContainer = myCookieContainer }) // TODO: test, probably this can be deleted
using (HttpClient client = new HttpClient())
{
var content = new FormUrlEncodedContent(values);
var response = client.PostAsync("http://169.254.200.200/api.php", content).Result;
var responseString = response.Content.ReadAsStringAsync().Result;
}
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private void CameraTurnOn()
{
/* On and Off command seems to be working as a toggle switch. Turn the camera on twices, turns
the camera on and off.
*/
var values = new Dictionary<string, string>
{
{ "v", "2" },
{ "action", "cam_action" },
{ "action_name", "power_on_um" },
{ "cids[]", this.cid}
};
using (var handler = new HttpClientHandler { CookieContainer = myCookieContainer }) // TODO: test, probably this can be deleted
using (HttpClient client = new HttpClient())
{
var content = new FormUrlEncodedContent(values);
var response = client.PostAsync("http://169.254.200.200/api.php", content).Result;
var responseString = response.Content.ReadAsStringAsync().Result;
//Log.Information(responseString);
}
}
public Uri getLiveStreamUri()
{
String baseAddressString = baseAddress.ToString();
baseAddressString = baseAddressString.TrimEnd('/');
return new Uri(baseAddressString + ":" + liveViewPortNumber + "/?action=stream");
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private async Task GetCam0InfoAsyncStartup()
{
/* On and Off command seems to be working as a toggle switch. Turn the camera on twices, turns
the camera on and off.
*/
Log.Information("[GetCam0InfoAsyncStartup] in method");
// Body to check cam status on bus 169.254.200.200, probably the first camera control box
var values = new Dictionary<string, string>
{
{ "v", "2" },
{ "action", "check_cam_state" },
{ "param", "1" },
{ "bid", "169.254.200.200" }
};
using (var handler = new HttpClientHandler { CookieContainer = myCookieContainer }) // TODO: test, probably this can be deleted
using (HttpClient client = new HttpClient())
{
Log.Information("[GetCam0InfoAsyncStartup] set dict");
var content = new FormUrlEncodedContent(values);
Log.Information("[GetCam0InfoAsyncStartup] URL encoded");
Log.Information(content.ToString());
var camInfo = new JObject();
//TODO, catch exceptions (https://forums.xamarin.com/discussion/101202/try-catch-on-httpclient-not-working)
try
{
var response = client.PostAsync("http://169.254.200.200/api.php", content).Result; // fix this Result shit (https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html)
Log.Information("[GetCam0InfoAsyncStartup] async post send");
var responseString = await response.Content.ReadAsStringAsync();
JObject allInfo = JObject.Parse(responseString);
Log.Information("[GetCam0InfoAsyncStartup] content read");
Log.Information("[GetCam0InfoAsyncStartup] JSON parsed");
camInfo = (JObject)allInfo["cams"][0];
connectionBoxConnected = true;
}
catch(Exception e)
{
connectionBoxConnected = false;
Log.Information("[GetCam0InfoAsyncStartup] " + e);
}
/* Example output when no camera is connected
{
"dummy": true,
"busnumber": -1,
"devicebusnumber": -1,
"modelname": "",
"serialnumber": "",
"bid": "169.254.200.200",
"cid": "169.254.200.200:-1:-1"
}
*/
if (camInfo.ContainsKey("liveviewportnumber"))
this.liveViewPortNumber = (int)camInfo["liveviewportnumber"];
if (camInfo.ContainsKey("modelname"))
this.modelName = camInfo["modelname"].ToString();
if (camInfo.ContainsKey("serialnumber"))
this.serialNumber = camInfo["serialnumber"].ToString();
if (camInfo.ContainsKey("bid"))
this.bid = camInfo["bid"].ToString();
if (camInfo.ContainsKey("cid"))
this.cid = camInfo["cid"].ToString();
/* Check if a camera is connected
TODO: explain working of dummy key
*/
if (camInfo.ContainsKey("dummy"))
{
this.cameraConnected = false;
}
else
{
this.cameraConnected = true;
}
if (this.cameraConnected)
{
Log.Information("\tFound a connected camera");
Log.Information("\t\tLive view port number: {0}", this.liveViewPortNumber);
Log.Information("\t\tBID: {0}", bid);
Log.Information("\t\tCID: {0}", cid);
Log.Information("\t\tModel name: {0}", modelName);
Log.Information("\t\tSerial nr: {0}\r\n", serialNumber);
}
else
Log.Information("No camera found");
}
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
public async Task CameraTurnOffAsync()
{
/* On and Off command seems to be working as a toggle switch. Turn the camera on twices, turns
the camera on and off.
*/
var values = new Dictionary<string, string>
{
{ "v", "2" },
{ "action", "cam_action" },
{ "action_name", "power_off_um" },
{ "cids[]", "169.254.200.200:1:17" } // wanneer camera ingeschakeld is
};
using (var handler = new HttpClientHandler { CookieContainer = myCookieContainer }) // TODO: test, probably this can be deleted
using (HttpClient client = new HttpClient())
{
var content = new FormUrlEncodedContent(values);
try
{
var response = await client.PostAsync("http://169.254.200.200/api.php", content);
var responseString = await response.Content.ReadAsStringAsync();
}
catch (Exception e)
{
Log.Information(e.ToString());
}
}
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private void CameraRecordStartCommand()
{
var values = new Dictionary<string, string>
{
{ "v", "2" },
{ "action", "cam_action" },
{ "action_name", "movie_recording_start_usb" },
{ "cids[]", "169.254.200.200:1:3" },
{ "browser_key", this.browserKey }
};
var content = new FormUrlEncodedContent(values);
Log.Information("Sending start command to cid: {0}, browser_key: {1}", this.cid, this.browserKey);
using (var handler = new HttpClientHandler() { CookieContainer = this.myCookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
try
{
var response = client.PostAsync("/api.php", content).Result;
var responseString = response.Content.ReadAsStringAsync().Result;
Log.Information(responseString);
}
catch (Exception e)
{
Log.Information(e.ToString());
}
}
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private void CameraRecordStopCommand()
{
var values = new Dictionary<string, string>
{
{ "v", "2" },
{ "action", "cam_action" },
{ "action_name", "movie_recording_stop_usb" },
{ "cids[]", "169.254.200.200:1:3" },
{ "browser_key", this.browserKey }
};
var content = new FormUrlEncodedContent(values);
using (var handler = new HttpClientHandler() { CookieContainer = this.myCookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
try
{
var response = client.PostAsync("/api.php", content).Result;
var responseString = response.Content.ReadAsStringAsync().Result;
Log.Information(responseString);
}
catch(Exception e)
{
Log.Information(e.ToString());
}
}
}
/// <summary>
/// TODO
/// </summary>
/// <returns></returns>
private async Task getBrowserKey()
{
var responseString = "";
using (var handler = new HttpClientHandler { CookieContainer = myCookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
try
{
var response = await client.GetAsync("/values.php?v=" + this.timestampInit);
responseString = await response.Content.ReadAsStringAsync();
}
catch (Exception e)
{
Log.Information(e.ToString());
}
}
/* Grab the value from browserKey, output is like this:
*
var serverValues = {
"browserKey": "bd198f83",
"camParamKeys": ["Compression_Setting", "White_Balance", "Focus_Mode",
"Exposure_Metering_Mode", "Flash_Mode", "Exposure_Program_Mode", "Drive_Mode"
*/
// TODO; check if a val
string pattern = @"(?<=browserKey"":"").+?(?="")";
Match m = Regex.Match(responseString, pattern);
//Log.Information("'{0}' found at position {1}", m.Value, m.Index);
if (m.Success)
{
this.browserKey = m.Value;
this.connectionBoxConnected = true;
}
else
{
this.connectionBoxConnected = false;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment