Compare commits

...

1 Commits

Author SHA1 Message Date
Thomas Klaehn
35db2c1f58 Add camera control
Signed-off-by: Thomas Klaehn <thomas.klaehn@perinet.io>
2025-09-11 08:47:20 +02:00
4 changed files with 141 additions and 37 deletions

View File

@@ -0,0 +1,98 @@
package apiservice_camera
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
apiservice_relay "powerswitch/internal/apiservice/relay"
)
type state string
type State struct {
State state `json:"state"`
}
const (
StateOn state = "on"
StateOff state = "off"
id int = 2
)
var (
logger log.Logger = *log.Default()
)
func init() {
logger.SetFlags(log.Llongfile | log.Ltime)
}
func AddHandler() {
http.HandleFunc("GET /camera/state", handle_get_powerstate)
http.HandleFunc("PATCH /camera/state", handle_patch_powerstate)
}
func GetState() (bool, error) {
res, err := apiservice_relay.GetRelay(id)
return !res, err
}
func SetState(state bool) error {
return apiservice_relay.SetRelay(id, !state)
}
func handle_get_powerstate(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-type", "application/json; charset=utf-8;")
state, err := apiservice_relay.GetRelay(id)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error())))
return
}
var res State
if state {
res.State = StateOff
} else {
res.State = StateOn
}
tmp, err := json.Marshal(res)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error())))
return
}
w.WriteHeader(http.StatusOK)
w.Write(tmp)
}
func handle_patch_powerstate(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-type", "application/json; charset=utf-8;")
tmp, err := io.ReadAll(r.Body)
if err != nil {
w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error())))
w.WriteHeader(http.StatusInternalServerError)
return
}
var state State
err = json.Unmarshal(tmp, &state)
if err != nil {
w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error())))
w.WriteHeader(http.StatusInternalServerError)
return
}
set_state := true
if state.State == StateOn {
set_state = false
}
err = apiservice_relay.SetRelay(id, set_state)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error())))
return
}
w.WriteHeader(http.StatusOK)
}

View File

@@ -6,6 +6,7 @@ import (
"io" "io"
"log" "log"
"net/http" "net/http"
apiservice_camera "powerswitch/internal/apiservice/camera"
apiservice_data "powerswitch/internal/apiservice/data" apiservice_data "powerswitch/internal/apiservice/data"
apiservice_power "powerswitch/internal/apiservice/power" apiservice_power "powerswitch/internal/apiservice/power"
"powerswitch/internal/app/process/octoprint" "powerswitch/internal/app/process/octoprint"
@@ -85,21 +86,32 @@ func handle_patch_printerstate(w http.ResponseWriter, r *http.Request) {
return return
} }
new_state := false
if state.State == StateOn { if state.State == StateOn {
err := apiservice_data.SetState(true) new_state = true
}
err = apiservice_data.SetState(new_state)
if err != nil { if err != nil {
logger.Print(err) logger.Print(err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error()))) w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error())))
return return
} }
err = apiservice_power.SetState(true) err = apiservice_power.SetState(new_state)
if err != nil { if err != nil {
logger.Print(err) logger.Print(err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error()))) w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error())))
return return
} }
err = apiservice_camera.SetState(new_state)
if err != nil {
logger.Print(err)
w.WriteHeader(http.StatusInternalServerError)
w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error())))
return
}
if state.State == StateOn {
err = octoprint.ReStart() err = octoprint.ReStart()
if err != nil { if err != nil {
logger.Print(err) logger.Print(err)
@@ -115,20 +127,6 @@ func handle_patch_printerstate(w http.ResponseWriter, r *http.Request) {
w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error()))) w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error())))
return return
} }
err = apiservice_power.SetState(false)
if err != nil {
logger.Print(err)
w.WriteHeader(http.StatusInternalServerError)
w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error())))
return
}
err = apiservice_data.SetState(false)
if err != nil {
logger.Print(err)
w.WriteHeader(http.StatusInternalServerError)
w.Write(json.RawMessage(fmt.Sprintf(`{"error": "%s"}`, err.Error())))
return
}
} }
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} }

View File

@@ -5,6 +5,7 @@ import (
"log" "log"
"net/http" "net/http"
apiservice_camera "powerswitch/internal/apiservice/camera"
apiservice_data "powerswitch/internal/apiservice/data" apiservice_data "powerswitch/internal/apiservice/data"
apiservice_power "powerswitch/internal/apiservice/power" apiservice_power "powerswitch/internal/apiservice/power"
apiservice_printer "powerswitch/internal/apiservice/printer" apiservice_printer "powerswitch/internal/apiservice/printer"
@@ -29,6 +30,7 @@ func main() {
host.Init() host.Init()
apiservice_camera.AddHandler()
apiservice_data.AddHandler() apiservice_data.AddHandler()
apiservice_power.AddHandler() apiservice_power.AddHandler()
apiservice_printer.AddHandler() apiservice_printer.AddHandler()

View File

@@ -7,17 +7,20 @@
<script type="text/javaScript"> <script type="text/javaScript">
const POWER_STATE_URL = "/power/state"; const POWER_STATE_URL = "/power/state";
const DATA_STATE_URL = "/data/state"; const DATA_STATE_URL = "/data/state";
const CAMERA_STATE_URL = "/camera/state";
const PRINTER_STATE_URL = "/printer/state"; const PRINTER_STATE_URL = "/printer/state";
function init() { function init() {
get_state(PRINTER_STATE_URL, "printer_slider"); get_state(PRINTER_STATE_URL, "printer_slider");
get_state(POWER_STATE_URL, "power_slider"); get_state(POWER_STATE_URL, "power_slider");
get_state(DATA_STATE_URL, "data_slider"); get_state(DATA_STATE_URL, "data_slider");
get_state(CAMERA_STATE_URL, "camera_slider");
setInterval(poll, 1000); setInterval(poll, 1000);
} }
function poll() { function poll() {
get_state(PRINTER_STATE_URL, "printer_slider"); get_state(PRINTER_STATE_URL, "printer_slider");
get_state(POWER_STATE_URL, "power_slider"); get_state(POWER_STATE_URL, "power_slider");
get_state(DATA_STATE_URL, "data_slider"); get_state(DATA_STATE_URL, "data_slider");
get_state(CAMERA_STATE_URL, "camera_slider");
} }
function get_state(url, target) { function get_state(url, target) {
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
@@ -64,20 +67,14 @@
url = POWER_STATE_URL; url = POWER_STATE_URL;
} else if(name === "data") { } else if(name === "data") {
url = DATA_STATE_URL; url = DATA_STATE_URL;
} else if(name === "camera") {
url = CAMERA_STATE_URL;
}else if(name === "printer") { }else if(name === "printer") {
url = PRINTER_STATE_URL; url = PRINTER_STATE_URL;
} }
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
xhr.open("PATCH", url); xhr.open("PATCH", url);
xhr.setRequestHeader("Content-type", "application/json; charset=utf-8"); xhr.setRequestHeader("Content-type", "application/json; charset=utf-8");
// xhr.onload = () => {
// var data = JSON.parse(xhr.responseText);
// if (xhr.readyState == 4 && xhr.status == "202") {
// console.log(data);
// } else {
// console.log(`Error: ${xhr.status}`);
// }
// };
xhr.send(obj); xhr.send(obj);
} }
</script> </script>
@@ -124,6 +121,15 @@
</label> </label>
</td> </td>
</tr> </tr>
<tr>
<td>Kamera:</td>
<td>
<label class="switch">
<input id="camera_slider" type="checkbox" onchange="check(this, 'camera')">
<span class="slider round"></span>
</label>
</td>
</tr>
</table> </table>
</div> </div>
<div id="containerdiv"> <div id="containerdiv">