mirror of
https://github.com/RoganDawes/P4wnP1_aloa.git
synced 2025-03-17 13:21:50 +01:00
webclient,service,hid: Fixes of HIDScript state events; fix timestamp displaying
This commit is contained in:
parent
5657a98c17
commit
32846e652c
@ -167,6 +167,13 @@ func (avm *AsyncOttoVM) RunAsync(ctx context.Context, src interface{}, anonymous
|
||||
if caught == haltirq {
|
||||
job.ResultErr = errors.New(fmt.Sprintf("Execution of job %d on VM %d interrupted\n", job.Id, avm.Id))
|
||||
|
||||
avm.emitEvent(Event{
|
||||
Job:job,
|
||||
Vm:job.executingVM,
|
||||
Type:EventType_JOB_CANCELLED,
|
||||
Message:"Script execution cancelled",
|
||||
})
|
||||
|
||||
// signal Job finished
|
||||
job.SetFinished()
|
||||
return
|
||||
|
@ -1,3 +1,4 @@
|
||||
// +build linux
|
||||
|
||||
package hid
|
||||
|
||||
@ -301,12 +302,14 @@ func (ctl *HIDController) CancelAllBackgroundJobs() {
|
||||
for job,_ := range oldList {
|
||||
fmt.Printf("Cancelling Job %d\n", job.Id)
|
||||
job.Cancel()
|
||||
/*
|
||||
ctl.emitEvent(Event{
|
||||
Job:job,
|
||||
Vm:job.executingVM,
|
||||
Type:EventType_JOB_CANCELLED,
|
||||
Message:"Script execution cancelled",
|
||||
})
|
||||
*/
|
||||
}
|
||||
globalJobList = make(map[*AsyncOttoJob]bool) //Create new empty list
|
||||
globalJobListMutex.Unlock()
|
||||
|
@ -1,15 +1,15 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
pb "github.com/mame82/P4wnP1_go/proto"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/mame82/P4wnP1_go/common_web"
|
||||
"github.com/mame82/P4wnP1_go/hid"
|
||||
pb "github.com/mame82/P4wnP1_go/proto"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
"log"
|
||||
"github.com/mame82/P4wnP1_go/hid"
|
||||
"github.com/mame82/P4wnP1_go/common_web"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type EventManager struct {
|
||||
@ -53,7 +53,7 @@ func (em *EventManager) Emit(event *pb.Event) {
|
||||
}
|
||||
|
||||
func (em *EventManager) Write(p []byte) (n int, err error) {
|
||||
ev := ConstructEventLog("logWriter", 1, string(p))
|
||||
ev := ConstructEventLog("logWriter", LOG_LEVEL_INFORMATION, string(p))
|
||||
em.Emit(ev)
|
||||
return len(p), nil
|
||||
}
|
||||
@ -165,8 +165,32 @@ func ConstructEventNotifyStateChange(stateType common_web.EvtStateChangeType) *p
|
||||
}
|
||||
}
|
||||
|
||||
func ConstructEventLog(source string, level int, message string) *pb.Event {
|
||||
tJson, _ := time.Now().MarshalJSON()
|
||||
/*
|
||||
case 1:
|
||||
return prefix + "critical"
|
||||
case 2:
|
||||
return prefix + "error"
|
||||
case 3:
|
||||
return prefix + "warning"
|
||||
case 4:
|
||||
return prefix + "information"
|
||||
case 5:
|
||||
return prefix + "verbose"
|
||||
*/
|
||||
type LogLevel int
|
||||
const (
|
||||
LOG_LEVEL_UNDEFINED LogLevel = iota
|
||||
LOG_LEVEL_CRITICAL
|
||||
LOG_LEVEL_ERROR
|
||||
LOG_LEVEL_WARNING
|
||||
LOG_LEVEL_INFORMATION
|
||||
LOG_LEVEL_VERBOSE
|
||||
)
|
||||
|
||||
func ConstructEventLog(source string, level LogLevel, message string) *pb.Event {
|
||||
//tJson, _ := time.Now().MarshalJSON()
|
||||
|
||||
unixTimeMillis := time.Now().UnixNano() / 1e6
|
||||
|
||||
return &pb.Event{
|
||||
Type: common_web.EVT_LOG,
|
||||
@ -174,7 +198,7 @@ func ConstructEventLog(source string, level int, message string) *pb.Event {
|
||||
{Val: &pb.EventValue_Tstring{Tstring: source}},
|
||||
{Val: &pb.EventValue_Tint64{Tint64: int64(level)}},
|
||||
{Val: &pb.EventValue_Tstring{Tstring: message}},
|
||||
{Val: &pb.EventValue_Tstring{Tstring: string(tJson)}},
|
||||
{Val: &pb.EventValue_Tint64{Tint64: unixTimeMillis}}, //retrieve time in nano second accuracy and scale down to milliseconds
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -266,7 +290,8 @@ func ConstructEventHID(hidEvent hid.Event) *pb.Event {
|
||||
vmID = eVM.Id
|
||||
}
|
||||
|
||||
tJson, _ := time.Now().MarshalJSON()
|
||||
|
||||
unixTimeMillis := time.Now().UnixNano() / 1e6
|
||||
|
||||
return &pb.Event{
|
||||
Type: common_web.EVT_HID, //Type
|
||||
@ -278,7 +303,7 @@ func ConstructEventHID(hidEvent hid.Event) *pb.Event {
|
||||
{Val: &pb.EventValue_Tstring{Tstring: resString}}, //result String
|
||||
{Val: &pb.EventValue_Tstring{Tstring: errString}}, //error String (message in case of error)
|
||||
{Val: &pb.EventValue_Tstring{Tstring: message}}, //Mesage text of event
|
||||
{Val: &pb.EventValue_Tstring{Tstring: string(tJson)}}, //Timestamp of event genration
|
||||
{Val: &pb.EventValue_Tint64{Tint64: unixTimeMillis}}, //Timestamp of event genration
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +547,7 @@ func (tam *TriggerActionManager) executeActionLog(evt *pb.Event, ta *pb.TriggerA
|
||||
}
|
||||
|
||||
fmt.Printf("Trigger '%s' fired -> executing action '%s'\n", triggerName, actionName)
|
||||
tam.rootSvc.SubSysEvent.Emit(ConstructEventLog("TriggerAction", 0, logMessage))
|
||||
tam.rootSvc.SubSysEvent.Emit(ConstructEventLog("TriggerAction", LOG_LEVEL_INFORMATION, logMessage))
|
||||
}
|
||||
|
||||
// checks if the triggerType of the given event (if trigger event at all), matches the TriggerType of the TriggerAction
|
||||
|
@ -3,12 +3,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gopherjs/gopherjs/js"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"time"
|
||||
pb "github.com/mame82/P4wnP1_go/proto/gopherjs"
|
||||
"context"
|
||||
"github.com/gopherjs/gopherjs/js"
|
||||
)
|
||||
|
||||
func O() *js.Object {
|
||||
@ -27,6 +24,14 @@ func StringToMD5(input string) string {
|
||||
return string(dst)
|
||||
}
|
||||
|
||||
func BytesToMD5(input []byte) string {
|
||||
sum := md5.Sum(input)
|
||||
dst := make([]byte, hex.EncodedLen(len(sum)))
|
||||
hex.Encode(dst, sum[:])
|
||||
return string(dst)
|
||||
}
|
||||
|
||||
/*
|
||||
func UploadHIDScript(filename string, content string) (err error) {
|
||||
ctx,cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
@ -65,4 +70,5 @@ func RunHIDScript(filename string, timeoutSeconds uint32) (job *pb.HIDScriptJob,
|
||||
},
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
@ -29,8 +29,11 @@ func InitCompHIDEvents() {
|
||||
func(vm *hvue.VM) interface{} {
|
||||
return vm.Get("$store").Get("state").Get("EventProcessor").Get("eventHidArray")
|
||||
}),
|
||||
hvue.Method("formatDate", func(vm *hvue.VM, timestamp *js.Object) interface{} {
|
||||
return js.Global.Get("Quasar").Get("utils").Get("date").Call("formatDate", timestamp, "YYYY-MM-DD HH:mm:ss Z")
|
||||
}),
|
||||
hvue.Method("evIdToString", func(vm *hvue.VM, evID int64) (res string) {
|
||||
println("EvID", evID)
|
||||
//println("EvID", evID)
|
||||
return common_web.EventTypeHIDName[evID]
|
||||
}),
|
||||
)
|
||||
@ -45,12 +48,16 @@ const (
|
||||
<div>
|
||||
<q-table
|
||||
:data="events"
|
||||
:columns="[{name:'type', field: 'evtype', label: 'Event Type', align: 'left'}, {name:'vmid', field: 'vmId', label: 'VM ID', align: 'left'}, {name:'jobid', field: 'jobId', label: 'Job ID', align: 'left'}, {name:'haserror', field: 'hasError', label: 'Has error', align: 'left'}, {name:'res', field: 'result', label: 'Result', align: 'left'}, {name:'errormsg', field: 'error', label: 'Error', align: 'left'}, {name:'msg', field: 'message', label: 'Message', align: 'left'}, {name:'timestamp', field: 'time', label: 'Time', align: 'left'}]"
|
||||
:columns="[{name:'timestamp', field: 'time', label: 'Time', align: 'left'}, {name:'type', field: 'evtype', label: 'Event Type', align: 'left'}, {name:'vmid', field: 'vmId', label: 'VM ID', align: 'left'}, {name:'jobid', field: 'jobId', label: 'Job ID', align: 'left'}, {name:'haserror', field: 'hasError', label: 'Has error', align: 'left'}, {name:'res', field: 'result', label: 'Result', align: 'left'}, {name:'errormsg', field: 'error', label: 'Error', align: 'left'}, {name:'msg', field: 'message', label: 'Message', align: 'left'}]"
|
||||
row-key="name"
|
||||
:pagination="pagination"
|
||||
hide-bottom
|
||||
>
|
||||
|
||||
<q-td slot="body-cell-timestamp" slot-scope="props" :props="props">
|
||||
{{ formatDate(props.value) }}
|
||||
</q-td>
|
||||
|
||||
<q-td slot="body-cell-type" slot-scope="props" :props="props">
|
||||
{{ evIdToString(props.value) }}
|
||||
</q-td>
|
||||
|
@ -123,13 +123,16 @@ ScriptSource string `js:"textSource"`
|
||||
<q-popover>
|
||||
{{ job.textResult }}
|
||||
</q-popover>
|
||||
<q-tooltip>
|
||||
show job result
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</q-item-side>
|
||||
<q-item-side right v-if="!job.hasSucceeded && !job.hasFailed">
|
||||
<q-btn flat round dense color="negative" icon="cancel" @click="cancel">
|
||||
<q-popover>
|
||||
<q-tooltip>
|
||||
cancel HIDScript job {{ job.id }}
|
||||
</q-popover>
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</q-item-side>
|
||||
</q-item>
|
||||
@ -141,15 +144,31 @@ ScriptSource string `js:"textSource"`
|
||||
compHIDJobOverviewTemplate = `
|
||||
<q-card class="full-height">
|
||||
<q-list>
|
||||
<q-list-header>Running</q-list-header>
|
||||
<hid-job-overview-item v-for="job in $store.getters.hidjobsRunning" :job="job" :key="job.id"></hid-job-overview-item>
|
||||
<q-collapsible opened icon-toggle>
|
||||
<template slot="header">
|
||||
<q-item-main label="Running jobs" :sublabel="'(' + $store.getters.hidjobsRunning.length + ' running jobs)'"/>
|
||||
<q-item-side v-if="$store.getters.hidjobsRunning.length > 0" right>
|
||||
<q-btn icon="cancel" color="red" @click="$store.dispatch('cancelAllHIDJobs')" round inverted flat>
|
||||
<q-tooltip>
|
||||
cancel all running HIDScript jobs
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</q-item-side>
|
||||
</template>
|
||||
<hid-job-overview-item v-for="job in $store.getters.hidjobsRunning" :job="job" :key="job.id"></hid-job-overview-item>
|
||||
</q-collapsible>
|
||||
</q-list>
|
||||
|
||||
<q-list>
|
||||
<q-collapsible opened icon-toggle>
|
||||
<q-collapsible opened icon-toggle>
|
||||
<template slot="header">
|
||||
<q-item-main label="Succeeded" :sublabel="'(' + $store.getters.hidjobsSucceeded.length + ' successful jobs)'"/>
|
||||
<q-item-side v-if="$store.getters.hidjobsSucceeded.length > 0" right>
|
||||
<q-btn icon="delete" color="red" @click="$store.dispatch('removeSucceededHidJobs')" round inverted flat />
|
||||
<q-btn icon="delete" color="red" @click="$store.dispatch('removeSucceededHidJobs')" round inverted flat>
|
||||
<q-tooltip>
|
||||
delete succeeded HID jobs from list
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
</q-item-side>
|
||||
</template>
|
||||
<hid-job-overview-item v-for="job in $store.getters.hidjobsSucceeded" :job="job" :key="job.id"></hid-job-overview-item>
|
||||
@ -160,7 +179,12 @@ compHIDJobOverviewTemplate = `
|
||||
<template slot="header">
|
||||
<q-item-main label="Failed" :sublabel="'(' + $store.getters.hidjobsFailed.length + ' failed jobs)'"/>
|
||||
<q-item-side v-if="$store.getters.hidjobsFailed.length > 0" right>
|
||||
<q-btn icon="delete" color="red" @click="$store.dispatch('removeFailedHidJobs')" round inverted flat />
|
||||
<q-btn icon="delete" color="red" @click="$store.dispatch('removeFailedHidJobs')" round inverted flat>
|
||||
<q-tooltip>
|
||||
delete failed HID jobs from list
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
</q-item-side>
|
||||
</template>
|
||||
<hid-job-overview-item v-for="job in $store.getters.hidjobsFailed" :job="job" :key="job.id"></hid-job-overview-item>
|
||||
|
@ -5,7 +5,6 @@ package main
|
||||
import (
|
||||
"github.com/gopherjs/gopherjs/js"
|
||||
"github.com/mame82/hvue"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type CompHIDScriptCodeEditorData struct {
|
||||
@ -13,28 +12,6 @@ type CompHIDScriptCodeEditorData struct {
|
||||
CodeMirrorOptions *CodeMirrorOptionsType `js:"codemirrorOptions"`
|
||||
}
|
||||
|
||||
// ToDo: Change into action of vuex store
|
||||
func SendAndRun(vm *hvue.VM) {
|
||||
sourceCode := vm.Get("$store").Get("state").Get("currentHIDScriptSource").String()
|
||||
md5 := StringToMD5(sourceCode) //Calculate MD5 hexstring of current script content
|
||||
|
||||
go func() {
|
||||
timeout := uint32(0)
|
||||
err := UploadHIDScript(md5, sourceCode)
|
||||
if err != nil {
|
||||
QuasarNotifyError("Error uploading script", err.Error(), QUASAR_NOTIFICATION_POSITION_TOP)
|
||||
return
|
||||
}
|
||||
job,err := RunHIDScript(md5, timeout)
|
||||
if err != nil {
|
||||
QuasarNotifyError("Error starting script as background job", err.Error(), QUASAR_NOTIFICATION_POSITION_TOP)
|
||||
return
|
||||
}
|
||||
|
||||
QuasarNotifySuccess("Script started successfully", "Job ID " + strconv.Itoa(int(job.Id)), QUASAR_NOTIFICATION_POSITION_TOP)
|
||||
}()
|
||||
}
|
||||
|
||||
type CodeMirrorMode struct {
|
||||
*js.Object
|
||||
Name string `js:"name"`
|
||||
@ -80,7 +57,6 @@ func InitComponentsHIDScript() {
|
||||
"hid-script-code-editor",
|
||||
hvue.Template(compHIDScriptCodeEditorTemplate),
|
||||
hvue.DataFunc(newCompHIDScriptCodeEditorData),
|
||||
hvue.Method("SendAndRun", SendAndRun),
|
||||
hvue.ComputedWithGetSet(
|
||||
"scriptContent",
|
||||
func(vm *hvue.VM) interface{} {
|
||||
@ -133,7 +109,10 @@ func InitComponentsHIDScript() {
|
||||
vm.Get("$q").Call("notify", "store " + name.String())
|
||||
vm.Store.Call("dispatch", VUEX_ACTION_STORE_CURRENT_HID_SCRIPT_SOURCE_TO_REMOTE_FILE, name)
|
||||
}),
|
||||
hvue.Method("SendAndRun", SendAndRun),
|
||||
hvue.Method("SendAndRun", func (vm *hvue.VM) {
|
||||
sourceCode := vm.Get("$store").Get("state").Get("currentHIDScriptSource").String()
|
||||
vm.Store.Call("dispatch", VUEX_ACTION_AND_AND_RUN_HID_SCRIPT, sourceCode)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gopherjs/gopherjs/js"
|
||||
"github.com/mame82/hvue"
|
||||
)
|
||||
|
||||
@ -30,22 +31,25 @@ func InitCompLogger() {
|
||||
hvue.NewComponent(
|
||||
"logger",
|
||||
hvue.Template(compLoggerTemplate),
|
||||
// hvue.DataFunc(NewLoggerData),
|
||||
// hvue.MethodsOf(&CompLoggerData{}),
|
||||
hvue.DataFunc(func(vm *hvue.VM) interface{} {
|
||||
data := &struct {
|
||||
*js.Object
|
||||
Pagination *jsDataTablePagination `js:"pagination"`
|
||||
}{Object:O()}
|
||||
|
||||
data.Pagination = newPagination(0, 1)
|
||||
|
||||
return data
|
||||
}),
|
||||
hvue.Method("logLevelClass", LogLevelClass),
|
||||
hvue.PropObj("max-entries", hvue.Types(hvue.PNumber), hvue.Default(5)),
|
||||
hvue.Created(func(vm *hvue.VM) {
|
||||
println("OnCreated")
|
||||
// vm.Call("StartListening")
|
||||
}),
|
||||
hvue.Destroyed(func(vm *hvue.VM) {
|
||||
println("OnDestroyed")
|
||||
// vm.Call("StopListening")
|
||||
}),
|
||||
|
||||
hvue.Computed("classFromLevel", func(vm *hvue.VM) interface{} {
|
||||
return "info"
|
||||
}),
|
||||
hvue.Method("formatDate", func(vm *hvue.VM, timestamp *js.Object) interface{} {
|
||||
return js.Global.Get("Quasar").Get("utils").Get("date").Call("formatDate", timestamp, "YYYY-MM-DD HH:mm:ss Z")
|
||||
}),
|
||||
hvue.Computed("logArray",
|
||||
func(vm *hvue.VM) interface{} {
|
||||
return vm.Get("$store").Get("state").Get("EventProcessor").Get("logArray")
|
||||
@ -57,7 +61,24 @@ func InitCompLogger() {
|
||||
const (
|
||||
|
||||
compLoggerTemplate = `
|
||||
<q-page>
|
||||
<q-page padding>
|
||||
<q-card>
|
||||
<div>
|
||||
<q-table
|
||||
:data="logArray"
|
||||
:columns="[{name:'logTime', field: 'time', label: 'Time', align: 'left'}, {name:'logSource', field: 'source', label: 'Source', align: 'left'}, {name:'logLevel', field: 'level', label: 'Level', align: 'left'}, {name:'logMessage', field: 'message', label: 'Message', align: 'left'}]"
|
||||
row-key="name"
|
||||
:pagination="pagination"
|
||||
hide-bottom
|
||||
>
|
||||
<q-td slot="body-cell-logTime" slot-scope="props" :props="props">
|
||||
{{ formatDate(props.value) }}
|
||||
</q-td>
|
||||
</q-table>
|
||||
</div>
|
||||
</q-card>
|
||||
|
||||
<!--
|
||||
<div class="logger">
|
||||
<table class="log-entries">
|
||||
<tr>
|
||||
@ -74,6 +95,7 @@ const (
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
-->
|
||||
</q-page>
|
||||
`
|
||||
)
|
||||
|
@ -115,7 +115,7 @@ const (
|
||||
<div class="col-12">
|
||||
<q-card>
|
||||
<q-card-title>
|
||||
USB Gadget Settings
|
||||
USB Gadget Settings ({{ deploying }})
|
||||
</q-card-title>
|
||||
|
||||
<q-card-main>
|
||||
|
@ -359,19 +359,23 @@ const templateBluetoothPage = `
|
||||
</q-card>
|
||||
</div>
|
||||
|
||||
|
||||
<!--
|
||||
<div class="col-12">
|
||||
{{ CurrentControllerInfo }}
|
||||
</div>
|
||||
|
||||
-->
|
||||
<div class="col-12 col-lg">
|
||||
<bluetooth-controller :controllerInfo="CurrentControllerInfo"></bluetooth-controller>
|
||||
</div>
|
||||
<div class="col-12 col-lg">
|
||||
<bluetooth-controller-network-services :controllerInfo="CurrentControllerInfo"></bluetooth-controller-network-services>
|
||||
</div>
|
||||
<div class="col-12 col-lg">
|
||||
<bluetooth-agent :bluetoothAgent="CurrentBluetoothAgentSettings"></bluetooth-agent>
|
||||
<div class="row gutter-y-sm">
|
||||
<div class="col-12">
|
||||
<bluetooth-controller-network-services :controllerInfo="CurrentControllerInfo"></bluetooth-controller-network-services>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<bluetooth-agent :bluetoothAgent="CurrentBluetoothAgentSettings"></bluetooth-agent>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</q-page>
|
||||
|
@ -234,7 +234,7 @@ type jsLogEvent struct {
|
||||
EvLogSource string `js:"source"`
|
||||
EvLogLevel int `js:"level"`
|
||||
EvLogMessage string `js:"message"`
|
||||
EvLogTime string `js:"time"`
|
||||
EvLogTime int64 `js:"time"`
|
||||
}
|
||||
|
||||
//HID event
|
||||
@ -247,7 +247,7 @@ type jsHidEvent struct {
|
||||
Result string `js:"result"`
|
||||
Error string `js:"error"`
|
||||
Message string `js:"message"`
|
||||
EvLogTime string `js:"time"`
|
||||
EvLogTime int64 `js:"time"`
|
||||
}
|
||||
|
||||
func (jsEv *jsEvent) toLogEvent() (res *jsLogEvent, err error) {
|
||||
@ -273,10 +273,11 @@ func (jsEv *jsEvent) toLogEvent() (res *jsLogEvent, err error) {
|
||||
return nil, eNoLogEvent
|
||||
}
|
||||
|
||||
res.EvLogTime, ok = jsEv.Values[3].(string)
|
||||
res.EvLogTime, ok = jsEv.Values[3].(int64)
|
||||
if !ok {
|
||||
return nil, eNoLogEvent
|
||||
}
|
||||
println("EvLogTime", res.EvLogTime)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
@ -323,7 +324,7 @@ func (jsEv *jsEvent) toHidEvent() (res *jsHidEvent, err error) {
|
||||
return nil, eNoHidEvent
|
||||
}
|
||||
|
||||
res.EvLogTime, ok = jsEv.Values[7].(string)
|
||||
res.EvLogTime, ok = jsEv.Values[7].(int64)
|
||||
if !ok {
|
||||
return nil, eNoHidEvent
|
||||
}
|
||||
@ -341,7 +342,7 @@ type jsHidJobState struct {
|
||||
LastMessage string `js:"lastMessage"`
|
||||
TextResult string `js:"textResult"`
|
||||
// TextError string `js:"textError"`
|
||||
LastUpdateTime string `js:"lastUpdateTime"` //JSON timestamp from server
|
||||
LastUpdateTime int64 `js:"lastUpdateTime"` //JSON timestamp from server
|
||||
ScriptSource string `js:"textSource"`
|
||||
}
|
||||
|
||||
@ -392,7 +393,7 @@ func NewHIDJobStateList() *jsHidJobStateList {
|
||||
// state list, directly, but instead uses the "Vue.set()" method to update the object, while making vue aware of it.
|
||||
// This means: THE "UpdateEntry" METHOD RELIES ON THE PRESENCE OF THE "Vue" OBJECT IN JAVASCRIPT GLOBAL SCOPE. This again
|
||||
// means Vue.JS has to be loaded, BEFORE THIS METHOD IS CALLED"
|
||||
func (jl *jsHidJobStateList) UpdateEntry(id, vmId int64, hasFailed, hasSucceeded bool, message, textResult, lastUpdateTime, scriptSource string) {
|
||||
func (jl *jsHidJobStateList) UpdateEntry(id, vmId int64, hasFailed, hasSucceeded bool, message string, textResult string, lastUpdateTime int64, scriptSource string) {
|
||||
key := strconv.Itoa(int(id))
|
||||
|
||||
//Check if job exists, update existing one if already present
|
||||
@ -998,29 +999,10 @@ func (data *jsEventProcessor) handleHidEvent(hEv *jsHidEvent) {
|
||||
data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, hEv.HasError, false, hEv.Message, hEv.Error, hEv.EvLogTime, "")
|
||||
|
||||
QuasarNotifyError("HIDScript job " + strconv.Itoa(int(hEv.JobId)) + " failed", hEv.Error, QUASAR_NOTIFICATION_POSITION_TOP)
|
||||
/*
|
||||
notification := &QuasarNotification{Object: O()}
|
||||
notification.Message = "HIDScript job " + strconv.Itoa(int(hEv.JobId)) + " failed"
|
||||
notification.Detail = hEv.Error
|
||||
notification.Position = QUASAR_NOTIFICATION_POSITION_TOP
|
||||
notification.Type = QUASAR_NOTIFICATION_TYPE_NEGATIVE
|
||||
notification.Timeout = 5000
|
||||
QuasarNotify(notification)
|
||||
*/
|
||||
case common_web.HidEventType_JOB_SUCCEEDED:
|
||||
data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, hEv.HasError, true, hEv.Message, hEv.Result, hEv.EvLogTime, "")
|
||||
|
||||
QuasarNotifySuccess("HIDScript job " + strconv.Itoa(int(hEv.JobId)) + " succeeded", hEv.Result, QUASAR_NOTIFICATION_POSITION_TOP)
|
||||
|
||||
/*
|
||||
notification := &QuasarNotification{Object: O()}
|
||||
notification.Message = "HIDScript job " + strconv.Itoa(int(hEv.JobId)) + " succeeded"
|
||||
notification.Detail = hEv.Result
|
||||
notification.Position = QUASAR_NOTIFICATION_POSITION_TOP
|
||||
notification.Type = QUASAR_NOTIFICATION_TYPE_POSITIVE
|
||||
notification.Timeout = 5000
|
||||
QuasarNotify(notification)
|
||||
*/
|
||||
case common_web.HidEventType_JOB_CANCELLED:
|
||||
data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, true, false, hEv.Message, hEv.Message, hEv.EvLogTime, "")
|
||||
default:
|
||||
|
@ -47,19 +47,18 @@ func Router(router *js.Object) hvue.ComponentOption {
|
||||
func main() {
|
||||
println(GetBaseURL())
|
||||
|
||||
println("====================---------")
|
||||
store := InitGlobalState() //sets Vuex store in JS window.store
|
||||
store.Dispatch(VUEX_ACTION_START_EVENT_LISTEN)
|
||||
|
||||
// RpcClient.StartListening() //Start event listening after global state is initiated (contains the event handlers)
|
||||
|
||||
// ToDo: delete because debug
|
||||
// RpcClient.GetAllDeployedEthernetInterfaceSettings(time.Second*10)
|
||||
|
||||
router := NewVueRouter("/usb",
|
||||
VueRouterRoute("/usb","", "<usb-settings></usb-settings>"),
|
||||
router := NewVueRouter(
|
||||
"/usb",
|
||||
// route below could be used for an easter egg
|
||||
//VueRouterRoute("/","", "<usb-settings></usb-settings>"),
|
||||
VueRouterRoute("/usb","", "<usb-settings></usb-settings>"),
|
||||
VueRouterRoute("/hid","", "<hid-script></hid-script>"),
|
||||
VueRouterRoute("/hidjobs","", "<hid-job-event-overview></hid-job-event-overview>"),
|
||||
VueRouterRoute("/logger","", "<logger :max-entries='7'></logger>"),
|
||||
@ -88,25 +87,7 @@ println("====================---------")
|
||||
vm := hvue.NewVM(
|
||||
hvue.El("#app"),
|
||||
hvue.Template(templateMainApp),
|
||||
/*
|
||||
//add "testString" to data
|
||||
hvue.DataFunc(func(vm *hvue.VM) interface{} {
|
||||
data := struct{
|
||||
*js.Object
|
||||
TestString string `js:"testString"`
|
||||
SelectedTab string `js:"selectedTab"`
|
||||
}{Object: O()}
|
||||
data.SelectedTab = "USB"
|
||||
data.TestString = "type('hello');"
|
||||
return &data
|
||||
}),
|
||||
*/
|
||||
//add console to app as computed property, to allow debug output on vue events
|
||||
hvue.Computed(
|
||||
"console",
|
||||
func(vm *hvue.VM) interface{} {
|
||||
return js.Global.Get("console")
|
||||
}),
|
||||
hvue.Computed("state", func(vm *hvue.VM) interface{} {
|
||||
return vm.Get("$store").Get("state") //works only with Vuex store option added
|
||||
}),
|
||||
@ -118,7 +99,6 @@ println("====================---------")
|
||||
)
|
||||
// ToDo: remove next lines, debug code
|
||||
js.Global.Set("vm",vm)
|
||||
js.Global.Set("rpc", RpcClient)
|
||||
}
|
||||
|
||||
const templateMainApp = `
|
||||
@ -132,13 +112,13 @@ const templateMainApp = `
|
||||
</q-toolbar>
|
||||
<q-tabs>
|
||||
<q-route-tab default slot="title" to="usb" name="tab-usb" icon="usb" label="USB Settings"></q-route-tab>
|
||||
<q-route-tab slot="title" to="hid" name="tab-hid-script" icon="code" label="HIDScript"></q-route-tab>
|
||||
<q-route-tab slot="title" to="hidjobs" name="tab-hid-jobs" icon="schedule" label="HID Events"></q-route-tab>
|
||||
<q-route-tab slot="title" to="logger" name="tab-logger" icon="message" label="Event Log"></q-route-tab>
|
||||
<q-route-tab slot="title" to="network" name="tab-network" icon="settings_ethernet" label="Network settings"></q-route-tab>
|
||||
<q-route-tab slot="title" to="wifi" name="tab-wifi" icon="wifi" label="WiFi settings"></q-route-tab>
|
||||
<q-route-tab slot="title" to="triggeractions" name="tab-triggeraction" icon="whatshot" label="Trigger Actions"></q-route-tab>
|
||||
<q-route-tab slot="title" to="bluetooth" name="tab-bluetooth" icon="bluetooth" label="Bluetooth"></q-route-tab>
|
||||
<q-route-tab slot="title" to="network" name="tab-network" icon="settings_ethernet" label="Network settings"></q-route-tab>
|
||||
<q-route-tab slot="title" to="triggeractions" name="tab-triggeraction" icon="whatshot" label="Trigger Actions"></q-route-tab>
|
||||
<q-route-tab slot="title" to="hid" name="tab-hid-script" icon="keyboard" label="HIDScript"></q-route-tab>
|
||||
<!-- <q-route-tab slot="title" to="hidjobs" name="tab-hid-jobs" icon="schedule" label="HID Events"></q-route-tab> -->
|
||||
<q-route-tab slot="title" to="logger" name="tab-logger" icon="message" label="Event Log"></q-route-tab>
|
||||
</q-tabs>
|
||||
</q-layout-header>
|
||||
|
||||
@ -155,14 +135,6 @@ const templateMainApp = `
|
||||
<router-view></router-view>
|
||||
|
||||
<disconnect-modal :value="!$store.getters.isConnected"></disconnect-modal>
|
||||
<!--
|
||||
<q-modal v-model="!$store.getters.isConnected" minimized no-route-dismiss no-esc-dismiss no-backdrop-dismiss>
|
||||
<div style="padding: 50px">
|
||||
<div class="q-display-1 q-mb-md">No connection to server</div>
|
||||
<p>Trying to reconnect ... (attempt {{ $store.state.failedConnectionAttempts }})</p>
|
||||
</div>
|
||||
</q-modal>
|
||||
-->
|
||||
</q-page-container>
|
||||
|
||||
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -45,12 +46,14 @@ const (
|
||||
|
||||
//HIDScripts and jobs
|
||||
VUEX_ACTION_UPDATE_RUNNING_HID_JOBS = "updateRunningHidJobs"
|
||||
VUEX_ACTION_REMOVE_SUCCEEDED_HID_JOBS = "removeSucceededHidJobs"
|
||||
VUEX_ACTION_REMOVE_FAILED_HID_JOBS = "removeFailedHidJobs"
|
||||
VUEX_ACTION_REMOVE_SUCCEEDED_HID_JOBS = "removeSucceededHidJobs"
|
||||
VUEX_ACTION_REMOVE_FAILED_HID_JOBS = "removeFailedHidJobs"
|
||||
VUEX_ACTION_UPDATE_STORED_HID_SCRIPTS_LIST = "updateStoredHIDScriptsList"
|
||||
VUEX_ACTION_UPDATE_CURRENT_HID_SCRIPT_SOURCE_FROM_REMOTE_FILE = "updateCurrentHidScriptSourceFromRemoteFile"
|
||||
VUEX_ACTION_STORE_CURRENT_HID_SCRIPT_SOURCE_TO_REMOTE_FILE = "storeCurrentHidScriptSourceToRemoteFile"
|
||||
VUEX_ACTION_CANCEL_HID_JOB = "cancelHIDJob"
|
||||
VUEX_ACTION_CANCEL_HID_JOB = "cancelHIDJob"
|
||||
VUEX_ACTION_CANCEL_ALL_HID_JOBS = "cancelAllHIDJobs"
|
||||
VUEX_ACTION_AND_AND_RUN_HID_SCRIPT = "sendAndRunHIDScript"
|
||||
|
||||
VUEX_MUTATION_SET_CURRENT_HID_SCRIPT_SOURCE_TO = "setCurrentHIDScriptSource"
|
||||
VUEX_MUTATION_SET_STORED_HID_SCRIPTS_LIST = "setStoredHIDScriptsList"
|
||||
@ -155,6 +158,7 @@ func createGlobalStateStruct() GlobalState {
|
||||
state.Title = "P4wnP1 by MaMe82"
|
||||
state.CurrentHIDScriptSource = initHIDScript
|
||||
state.CurrentGadgetSettings = NewUSBGadgetSettings()
|
||||
state.CurrentlyDeployingGadgetSettings = false
|
||||
state.CurrentlyDeployingWifiSettings = false
|
||||
state.HidJobList = NewHIDJobStateList()
|
||||
state.TriggerActionList = NewTriggerActionSet()
|
||||
@ -204,7 +208,7 @@ func processEvent(evt *pb.Event, store *mvuex.Store, state *GlobalState) {
|
||||
case common_web.STATE_CHANGE_EVT_TYPE_NETWORK:
|
||||
store.Dispatch(VUEX_ACTION_UPDATE_ALL_ETHERNET_INTERFACE_SETTINGS)
|
||||
case common_web.STATE_CHANGE_EVT_TYPE_HID:
|
||||
store.Dispatch(VUEX_ACTION_UPDATE_RUNNING_HID_JOBS) // handled by dedicated listener
|
||||
//store.Dispatch(VUEX_ACTION_UPDATE_RUNNING_HID_JOBS) // handled by dedicated listener
|
||||
case common_web.STATE_CHANGE_EVT_TYPE_WIFI:
|
||||
store.Dispatch(VUEX_ACTION_UPDATE_WIFI_STATE)
|
||||
case common_web.STATE_CHANGE_EVT_TYPE_TRIGGER_ACTIONS:
|
||||
@ -254,9 +258,34 @@ func actionUpdateAllStates(store *mvuex.Store, context *mvuex.ActionContext, sta
|
||||
|
||||
}
|
||||
|
||||
func actionSendAndRunHIDScript(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState, scriptContent *js.Object) {
|
||||
go func() {
|
||||
strScriptContent := scriptContent.String()
|
||||
|
||||
println("Send and run HIDScript job")
|
||||
//fetch deployed gadget settings
|
||||
filename,err := RpcClient.UploadContentToTempFile(defaultTimeout, []byte(strScriptContent))
|
||||
if err != nil {
|
||||
println("Couldn't upload HIDScript job", err)
|
||||
QuasarNotifyError("Error uploading script", err.Error(), QUASAR_NOTIFICATION_POSITION_TOP)
|
||||
return
|
||||
}
|
||||
|
||||
job,err := RpcClient.RunHIDScriptJob(defaultTimeout, "/tmp/" + filename)
|
||||
if err != nil {
|
||||
println("Couldn't start HIDScript job", err)
|
||||
QuasarNotifyError("Error starting script as background job", err.Error(), QUASAR_NOTIFICATION_POSITION_TOP)
|
||||
return
|
||||
}
|
||||
|
||||
QuasarNotifySuccess("Script started successfully", "Job ID " + strconv.Itoa(int(job.Id)), QUASAR_NOTIFICATION_POSITION_TOP)
|
||||
|
||||
// ToDo: update HIDScriptJob list (should be done event based)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
func actionCancelHidJob(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState, jobID *js.Object) {
|
||||
|
||||
|
||||
go func() {
|
||||
id := uint32(jobID.Int())
|
||||
println("Cancel HIDScript job", id)
|
||||
@ -269,8 +298,21 @@ func actionCancelHidJob(store *mvuex.Store, context *mvuex.ActionContext, state
|
||||
|
||||
// ToDo: update HIDScriptJob list (should be done event based)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
func actionCancelAllHidJobs(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState) {
|
||||
go func() {
|
||||
println("Cancel all HIDScript jobs")
|
||||
//fetch deployed gadget settings
|
||||
err := RpcClient.CancelAllHIDScriptJobs(defaultTimeout)
|
||||
if err != nil {
|
||||
println("Couldn't cancel all HIDScript jobs", err)
|
||||
return
|
||||
}
|
||||
|
||||
// ToDo: update HIDScriptJob list (should be done event based)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
@ -932,7 +974,8 @@ func actionUpdateRunningHidJobs(store *mvuex.Store, context *mvuex.ActionContext
|
||||
|
||||
for _, jobstate := range jobstates {
|
||||
println("updateing jobstate", jobstate)
|
||||
state.HidJobList.UpdateEntry(jobstate.Id, jobstate.VmId, false, false, "initial job state", "", time.Now().String(), jobstate.Source)
|
||||
timeNowUnixMilli := time.Now().UnixNano()/1e6
|
||||
state.HidJobList.UpdateEntry(jobstate.Id, jobstate.VmId, false, false, "initial job state", "", timeNowUnixMilli, jobstate.Source)
|
||||
}
|
||||
}()
|
||||
|
||||
@ -1115,6 +1158,7 @@ func actionDeployCurrentGadgetSettings(store *mvuex.Store, context *mvuex.Action
|
||||
notification.Timeout = 2000
|
||||
QuasarNotify(notification)
|
||||
|
||||
return
|
||||
}()
|
||||
|
||||
return
|
||||
@ -1267,9 +1311,12 @@ func initMVuex() *mvuex.Store {
|
||||
mvuex.Action(VUEX_ACTION_START_EVENT_LISTEN, actionStartEventListen),
|
||||
mvuex.Action(VUEX_ACTION_STOP_EVENT_LISTEN, actionStopEventListen),
|
||||
|
||||
|
||||
mvuex.Action(VUEX_ACTION_REMOVE_SUCCEEDED_HID_JOBS, actionRemoveSucceededHidJobs),
|
||||
mvuex.Action(VUEX_ACTION_REMOVE_FAILED_HID_JOBS, actionRemoveFailedHidJobs),
|
||||
mvuex.Action(VUEX_ACTION_CANCEL_HID_JOB, actionCancelHidJob),
|
||||
mvuex.Action(VUEX_ACTION_CANCEL_ALL_HID_JOBS, actionCancelAllHidJobs),
|
||||
mvuex.Action(VUEX_ACTION_AND_AND_RUN_HID_SCRIPT, actionSendAndRunHIDScript),
|
||||
|
||||
|
||||
mvuex.Getter("triggerActions", func(state *GlobalState) interface{} {
|
||||
@ -1327,6 +1374,9 @@ func initMVuex() *mvuex.Store {
|
||||
}),
|
||||
)
|
||||
|
||||
store.Dispatch(VUEX_ACTION_START_EVENT_LISTEN)
|
||||
|
||||
/*
|
||||
// fetch deployed gadget settings
|
||||
store.Dispatch(VUEX_ACTION_UPDATE_CURRENT_USB_SETTINGS)
|
||||
|
||||
@ -1335,14 +1385,14 @@ func initMVuex() *mvuex.Store {
|
||||
|
||||
// Update WiFi state
|
||||
store.Dispatch(VUEX_ACTION_UPDATE_WIFI_STATE)
|
||||
|
||||
// propagate Vuex store to global scope to allow injecting it to Vue by setting the "store" option
|
||||
js.Global.Set("store", store)
|
||||
|
||||
*/
|
||||
|
||||
return store
|
||||
}
|
||||
|
||||
func InitGlobalState() *mvuex.Store {
|
||||
return initMVuex()
|
||||
store := initMVuex()
|
||||
// propagate Vuex store to global scope to allow injecting it to Vue by setting the "store" option
|
||||
js.Global.Set("store", store)
|
||||
return store
|
||||
}
|
||||
|
@ -29,6 +29,40 @@ func NewRpcClient(addr string) Rpc {
|
||||
return rcl
|
||||
}
|
||||
|
||||
func (rpc *Rpc) UploadContentToTempFile(timeout time.Duration, content []byte) (filename string, err error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
//create hex string of content MD5 sum
|
||||
filename = BytesToMD5(content)
|
||||
|
||||
//upload file to `/tmp/{md5_hash_hex}`
|
||||
_,err = rpc.Client.FSWriteFile(ctx,
|
||||
&pb.WriteFileRequest{
|
||||
Data:content,
|
||||
Append:false,
|
||||
Filename:filename,
|
||||
Folder: pb.AccessibleFolder_TMP,
|
||||
MustNotExist:false,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (rpc *Rpc) RunHIDScriptJob(timeout time.Duration, filepath string) (job *pb.HIDScriptJob, err error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
||||
//upload file to `/tmp/{md5_hash_hex}`
|
||||
return rpc.Client.HIDRunScriptJob(
|
||||
ctx,
|
||||
&pb.HIDScriptRequest{
|
||||
ScriptPath: filepath,
|
||||
TimeoutSeconds: uint32(0),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (rpc *Rpc) CancelHIDScriptJob(timeout time.Duration, jobID uint32) (err error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
|
Loading…
x
Reference in New Issue
Block a user