Started working on HID job state vue components and event signaling

This commit is contained in:
MaMe82 2018-08-01 18:09:50 +02:00
parent d061348087
commit 3b971750ae
9 changed files with 276 additions and 183 deletions

View File

@ -6,3 +6,40 @@ const (
EVT_HID = int64(2)
)
const (
HidEventType_JOB_STARTED = int64(0)
HidEventType_JOB_STOPPED = int64(1)
HidEventType_CONTROLLER_ABORTED = int64(2)
HidEventType_JOB_CANCELLED = int64(3)
HidEventType_JOB_SUCCEEDED = int64(4)
HidEventType_JOB_SUCCEEDED_NO_RESULT = int64(5)
HidEventType_JOB_FAILED = int64(6)
HidEventType_JOB_WAIT_LED_FINISHED = int64(7)
HidEventType_JOB_WAIT_LED_REPEATED_FINISHED = int64(8)
HidEventType_JOB_NO_FREE_VM = int64(9)
)
var EventType_name = map[int64]string{
0: "JOB STARTED",
1: "JOB STOPPED",
2: "CONTROLLER ABORTED",
3: "JOB CANCELLED",
4: "JOB SUCCEEDED",
5: "JOB SUCCEEDED WITHOUT RESULT",
6: "JOB FAILED",
7: "JOB WAIT LED FINISHED",
8: "JOB WAIT LED REPEATED FINISHED",
9: "JOB NO FREE VM",
}
/*
var EventType_value = map[string]int32{
"JOB_STARTED": 0,
"JOB_STOPPED": 1,
"CONTROLLER_ABORTED": 2,
"JOB_CANCELLED": 3,
}
*/

11
dist/www/index.html vendored
View File

@ -134,16 +134,7 @@
<logger :max-entries="7"></logger>
</tab>
<tab header="bar">
<table>
<tr>
<td>
<usb-settings></usb-settings>
</td>
<td>
<usb-settings></usb-settings>
</td>
</tr>
</table>
<hidjobs></hidjobs>
</tab>
</tabs>
</div>

View File

@ -150,13 +150,16 @@ type EventReceiver struct {
func ConstructEventLog(source string, level int, message string) *pb.Event {
tJson,_ := time.Now().MarshalJSON()
return &pb.Event{
Type: common_web.EVT_LOG,
Values: []*pb.EventValue{
{Val: &pb.EventValue_Tstring{Tstring:source} },
{Val: &pb.EventValue_Tint64{Tint64:int64(level)} },
{Val: &pb.EventValue_Tstring{Tstring:message} },
{Val: &pb.EventValue_Tstring{Tstring:time.Now().String()} },
{Val: &pb.EventValue_Tstring{Tstring:string(tJson)} },
},
}
}
@ -179,6 +182,8 @@ func ConstructEventHID(hidEvent hid.Event) *pb.Event {
}
if eVM := hidEvent.Vm; eVM != nil { vmID = eVM.Id }
tJson,_ := time.Now().MarshalJSON()
return &pb.Event{
Type: common_web.EVT_HID, //Type
Values: []*pb.EventValue{
@ -189,7 +194,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:time.Now().String()} },//Timestamp of event genration
{Val: &pb.EventValue_Tstring{Tstring:string(tJson)} },//Timestamp of event genration
},
}
}

View File

@ -0,0 +1,55 @@
// +build js
package main
import (
"github.com/mame82/hvue"
)
func InitCompHIDJob() {
hvue.NewComponent(
"hidjob",
hvue.Template(compHIDJobTemplate),
hvue.Computed("jobstate",
func(vm *hvue.VM) interface{} {
//fetch job and cast back to jobstate
job := &jsHidJobState{Object:vm.Get("job")}
switch {
case job.HasFailed && !job.HasSucceeded:
return "FAILED"
case job.HasSucceeded && !job.HasFailed:
return "SUCCEEDED"
case !(job.HasFailed || job.HasSucceeded):
return "RUNNING"
default:
return "UNKNOWN_STATE"
}
}),
hvue.PropObj("job", hvue.Required),
)
}
const (
/*
// HIDJobList
type jsHidJobState struct {
*js.Object
Id int64 `js:"id"`
VmId int64 `js:"vmId"`
HasFailed bool `js:"hasFailed"`
HasSucceeded bool `js:"hasSucceeded"`
LastMessage string `js:"lastMessage"`
TextResult string `js:"textResult"`
TextError string `js:"textError"`
LastUpdateTime string `js:"lastUpdateTime"` //JSON timestamp from server
ScriptSource string `js:"textError"`
}
*/
compHIDJobTemplate = `
<li class="jobstate-entry" :class="jobstate">{{ job.id }}: {{ jobstate }}</li>
`
)

View File

@ -5,52 +5,73 @@ package main
import (
"github.com/gopherjs/gopherjs/js"
"github.com/mame82/hvue"
"github.com/mame82/P4wnP1_go/common_web"
)
type CompEthernetAddressesData2 struct {
type CompHIDJobsData struct {
*js.Object
}
func newCompEthernetAddressesData2(vm *hvue.VM) interface{} {
func newCompHIDJobsData(vm *hvue.VM) interface{} {
cc := &CompEthernetAddressesData2{
cc := &CompHIDJobsData{
Object: js.Global.Get("Object").New(),
}
return cc
}
func InitCompEthernetAddresses2() {
/*
o := vue.NewOption()
o.Name = "EthernetAddresses"
o.SetDataWithMethods(newCompEthernetAddressesData2)
o.Template = compEthernetAddressesTemplate2
o.AddProp("settings")
*/
func InitCompHIDJobs() {
hvue.NewComponent(
"ethernet-addresses",
hvue.Template(compEthernetAddressesTemplate2),
hvue.DataFunc(newCompEthernetAddressesData2),
hvue.PropObj("settings", hvue.Types(hvue.PObject)),
"hidjobs",
hvue.Template(compHIDJobsTemplate),
hvue.DataFunc(newCompHIDJobsData),
hvue.Computed("events",
func(vm *hvue.VM) interface{} {
return vm.Store.Get("state").Get("eventLog").Get("eventHidArray")
}),
hvue.Computed("jobs",
func(vm *hvue.VM) interface{} {
jobList := vm.Store.Get("state").Get("hidJobList").Get("jobs")
return js.Global.Get("Object").Call("values",jobList)
}),
hvue.Method("evIdToString", func (vm *hvue.VM, evID int64) (res string) {
println("EvID",evID)
return common_web.EventType_name[evID]
}),
)
}
const (
compEthernetAddressesTemplate2 = `
//{ "evtype": 0, "vmId": 2, "jobId": 3, "hasError": false, "result": "null", "error": "", "message": "Script started", "time": "2018-07-30 04:56:42.297533 +0000 UTC m=+7625.097825001" }
compHIDJobsTemplate = `
<div>
<table>
<tr>
<td>Host MAC address</td><td><input v-bind:value="settings.HostAddr" v-on:input="$emit('hostAddrChange', $event.target.value)"></td>
</tr>
<tr>
<td>Device MAC address</td><td><input v-bind:value="settings.DevAddr" v-on:input="$emit('devAddrChange', $event.target.value)"></td>
</tr>
</table>
<ul>
<hidjob v-for="job in jobs" :job="job"></hidjob>
</ul>
<table border="1">
<tr>
<th>Event Type</th>
<th>VM ID</th>
<th>Job ID</th>
<th>Has error</th>
<th>Result</th>
<th>Error</th>
<th>Message</th>
<th>Time</th>
</tr>
<tr v-for="e in events">
<td>{{ evIdToString(e.evtype) }}</td>
<td>{{ e.vmId }}</td>
<td>{{ e.jobId }}</td>
<td>{{ e.hasError }}</td>
<td>{{ e.result }}</td>
<td>{{ e.error }}</td>
<td>{{ e.message }}</td>
<td>{{ e.time }}</td>
</tr>
</table>
</div>
`
)

View File

@ -6,76 +6,6 @@ import (
"github.com/mame82/hvue"
)
/*
var preservedCOmpLoggerData *CompLoggerData = nil
type CompLoggerData struct {
*js.Object
LogArray *js.Object `js:"logArray"`
cancel context.CancelFunc
*sync.Mutex
}
func (data *CompLoggerData) AddEntry(vm *hvue.VM, ev *pb.Event ) {
go func() {
data.Lock()
defer data.Unlock()
logEv, err := DeconstructEventLog(ev)
if err != nil {
println("Logger: Error adding log entry, provided event couldn't be converted to log event")
return
}
data.LogArray.Call("push", logEv)
//reduce to length (note: kebab case 'max-entries' is translated to camel case 'maxEntries' by vue)
for data.LogArray.Length() > vm.Get("maxEntries").Int() {
data.LogArray.Call("shift") // remove first element
}
}()
}
func (data *CompLoggerData) StartListening(vm *hvue.VM) {
println("Start listening called", data, vm)
ctx,cancel := context.WithCancel(context.Background())
data.cancel = cancel
evStream, err := Client.Client.EventListen(ctx, &pb.EventRequest{ListenType: common.EVT_LOG})
if err != nil {
cancel()
println("Error listening fo Log events", err)
return
}
go func() {
defer cancel()
for {
event, err := evStream.Recv()
if err == io.EOF { break }
if err != nil { return }
//println("Event: ", event)
data.AddEntry(vm, event)
}
return
}()
}
func (data *CompLoggerData) StopListening(vm *hvue.VM) {
println("Stop listening called", data, vm)
data.cancel()
}
*/
func LogLevelClass(vm *hvue.VM, level int) string {
prefix := "log-entry log-entry-level-"
switch level {
@ -94,19 +24,6 @@ func LogLevelClass(vm *hvue.VM, level int) string {
}
}
/*
func NewLoggerData(vm *hvue.VM) interface{} {
loggerVmData := &CompLoggerData{
Object: js.Global.Get("Object").New(),
}
loggerVmData.Mutex = &sync.Mutex{}
loggerVmData.LogArray = js.Global.Get("Array").New()
return loggerVmData
}
*/
func InitCompLogger() {

View File

@ -10,9 +10,11 @@ import (
"context"
"io"
"github.com/mame82/P4wnP1_go/common_web"
"strconv"
)
var eNoLogEvent = errors.New("No log event")
var eNoHidEvent = errors.New("No HID event")
/* USB Gadget types corresponding to gRPC messages */
@ -175,6 +177,19 @@ type jsLogEvent struct {
EvLogTime string `js:"time"`
}
//HID event
type jsHidEvent struct {
*js.Object
EvType int64 `js:"evtype"`
VMId int64 `js:"vmId"`
JobId int64 `js:"jobId"`
HasError bool `js:"hasError"`
Result string `js:"result"`
Error string `js:"error"`
Message string `js:"message"`
EvLogTime string `js:"time"`
}
func (jsEv *jsEvent) toLogEvent() (res *jsLogEvent, err error) {
if jsEv.Type != common_web.EVT_LOG || len(jsEv.Values) != 4 { return nil,eNoLogEvent}
res = &jsLogEvent{Object:O()}
@ -196,49 +211,102 @@ func (jsEv *jsEvent) toLogEvent() (res *jsLogEvent, err error) {
return res,nil
}
/*
func DeconstructEventLog(gRPCEv *pb.Event) (res *jsLogEvent, err error) {
if gRPCEv.Type != common.EVT_LOG { return nil,errors.New("No log event")}
func (jsEv *jsEvent) toHidEvent() (res *jsHidEvent, err error) {
if jsEv.Type != common_web.EVT_HID || len(jsEv.Values) != 8 { return nil,eNoHidEvent}
res = &jsHidEvent{Object:O()}
res = &jsLogEvent{Object:O()}
switch vT := gRPCEv.Values[0].Val.(type) {
case *pb.EventValue_Tstring:
res.EvLogSource = vT.Tstring
default:
return nil, errors.New("Value at position 0 has wrong type for a log event")
}
switch vT := gRPCEv.Values[1].Val.(type) {
case *pb.EventValue_Tint64:
res.EvLogLevel = int(vT.Tint64)
default:
return nil, errors.New("Value at position 1 has wrong type for a log event")
}
switch vT := gRPCEv.Values[2].Val.(type) {
case *pb.EventValue_Tstring:
res.EvLogMessage = vT.Tstring
default:
return nil, errors.New("Value at position 2 has wrong type for a log event")
}
switch vT := gRPCEv.Values[3].Val.(type) {
case *pb.EventValue_Tstring:
res.EvLogTime = vT.Tstring
default:
return nil, errors.New("Value at position 3 has wrong type for a log event")
}
var ok bool
res.EvType,ok = jsEv.Values[0].(int64)
if !ok { return nil,eNoHidEvent }
return res, nil
res.VMId,ok = jsEv.Values[1].(int64)
if !ok { return nil,eNoHidEvent}
res.JobId,ok = jsEv.Values[2].(int64)
if !ok { return nil,eNoHidEvent}
res.HasError,ok = jsEv.Values[3].(bool)
if !ok { return nil,eNoHidEvent}
res.Result,ok = jsEv.Values[4].(string)
if !ok { return nil,eNoHidEvent}
res.Error,ok = jsEv.Values[5].(string)
if !ok { return nil,eNoHidEvent}
res.Message,ok = jsEv.Values[6].(string)
if !ok { return nil,eNoHidEvent}
res.EvLogTime,ok = jsEv.Values[7].(string)
if !ok { return nil,eNoLogEvent}
return res,nil
}
/* HIDJobList */
type jsHidJobState struct {
*js.Object
Id int64 `js:"id"`
VmId int64 `js:"vmId"`
HasFailed bool `js:"hasFailed"`
HasSucceeded bool `js:"hasSucceeded"`
LastMessage string `js:"lastMessage"`
TextResult string `js:"textResult"`
TextError string `js:"textError"`
LastUpdateTime string `js:"lastUpdateTime"` //JSON timestamp from server
ScriptSource string `js:"textError"`
}
type jsHidJobStateList struct {
*js.Object
Jobs *js.Object `js:"jobs"`
}
func NewHIDJobStateList() *jsHidJobStateList {
jl := &jsHidJobStateList{Object:O()}
jl.Jobs = O()
//ToDo: Delete adding a test job
jl.UpdateEntry(99,1,false,false, "This is the latest event message", "current result", "current error","16:00", "type('hello world')")
jl.UpdateEntry(100,1,false,true, "SUCCESS", "current result", "current error","16:00", "type('hello world')")
jl.UpdateEntry(101,1,true,false, "FAIL", "current result", "current error","16:00", "type('hello world')")
jl.UpdateEntry(102,1,true,true, "Error and Success at same time --> UNKNOWN", "current result", "current error","16:00", "type('hello world')")
jl.UpdateEntry(102,1,true,true, "Error and Success at same time --> UNKNOWN, repeated ID", "current result", "current error","16:00", "type('hello world')")
return jl
}
func (jl *jsHidJobStateList) UpdateEntry(id, vmId int64, hasFailed, hasSucceeded bool, message, textResult, textError, lastUpdateTime, scriptSource string) {
//Create job object
j := &jsHidJobState{Object:O()}
j.Id = id
j.VmId = vmId
j.HasFailed = hasFailed
j.HasSucceeded = hasSucceeded
j.LastMessage = message
j.TextResult = textResult
j.TextError = textError
j.LastUpdateTime = textError
if len(scriptSource) > 0 {j.ScriptSource = scriptSource}
jl.Jobs.Set(strconv.Itoa(int(j.Id)), j) //jobs["j.ID"]=j
}
func (jl *jsHidJobStateList) DeleteEntry(id int64) {
jl.Delete(strconv.Itoa(int(id))) //JS version
//delete(jl.Jobs, strconv.Itoa(int(id)))
}
*/
/* EVENT LOGGER */
type jsLoggerData struct {
*js.Object
LogArray *js.Object `js:"logArray"`
EventArray *js.Object `js:"eventArray"`
cancel context.CancelFunc
LogArray *js.Object `js:"logArray"`
HidEventArray *js.Object `js:"eventHidArray"`
cancel context.CancelFunc
*sync.Mutex
MaxEntries int `js:"maxEntries"`
MaxEntries int `js:"maxEntries"`
}
func NewLogger(maxEntries int) *jsLoggerData {
@ -248,7 +316,7 @@ func NewLogger(maxEntries int) *jsLoggerData {
loggerVmData.Mutex = &sync.Mutex{}
loggerVmData.LogArray = js.Global.Get("Array").New()
loggerVmData.EventArray = js.Global.Get("Array").New()
loggerVmData.HidEventArray = js.Global.Get("Array").New()
loggerVmData.MaxEntries = maxEntries
return loggerVmData
@ -256,43 +324,38 @@ func NewLogger(maxEntries int) *jsLoggerData {
/* This method gets internalized and therefor the mutex won't be accessible*/
func (data *jsLoggerData) AddEntry(ev *pb.Event ) {
// println("ADD ENTRY", ev)
// println("ADD ENTRY", ev)
go func() {
/*
data.Lock()
defer data.Unlock()
*/
/*
data.Lock()
defer data.Unlock()
*/
//if LOG event add to logArray
jsEv := NewJsEventFromNative(ev)
println("JS from native", jsEv)
if jsEv.Type == common_web.EVT_LOG {
switch jsEv.Type {
//if LOG event add to logArray
case common_web.EVT_LOG:
if logEv,err := jsEv.toLogEvent(); err == nil {
data.LogArray.Call("push", logEv)
} else {
println("couldn't convert to LogEvent: ", jsEv)
}
} else {
data.EventArray.Call("push", jsEv)
//if HID event add to eventHidArray
case common_web.EVT_HID:
if hidEv,err := jsEv.toHidEvent(); err == nil {
data.HidEventArray.Call("push", hidEv)
} else {
println("couldn't convert to HidEvent: ", jsEv)
}
}
/*
logEv, err := DeconstructEventLog(ev)
if err != nil {
println("Logger: Error adding log entry, provided event couldn't be converted to log event")
return
}
data.LogArray.Call("push", logEv)
*/
//reduce to length (note: kebab case 'max-entries' is translated to camel case 'maxEntries' by vue)
for data.LogArray.Length() > data.MaxEntries {
data.LogArray.Call("shift") // remove first element
}
for data.EventArray.Length() > data.MaxEntries {
data.EventArray.Call("shift") // remove first element
for data.HidEventArray.Length() > data.MaxEntries {
data.HidEventArray.Call("shift") // remove first element
}
}()
@ -306,7 +369,7 @@ func (data *jsLoggerData) StartListening() {
ctx,cancel := context.WithCancel(context.Background())
data.cancel = cancel
evStream, err := Client.Client.EventListen(ctx, &pb.EventRequest{ListenType: common_web.EVT_LOG})
evStream, err := Client.Client.EventListen(ctx, &pb.EventRequest{ListenType: common_web.EVT_ANY})
if err != nil {
cancel()
println("Error listening fo Log events", err)

View File

@ -71,6 +71,8 @@ func main() {
InitGlobalState() //sets Vuex store in JS window.store
InitCompHIDJob()
InitCompHIDJobs()
InitCompModal()
InitCompEthernetAddresses2()
InitCompToggleSwitch()

View File

@ -48,6 +48,7 @@ type GlobalState struct {
CurrentHIDScriptSource string `js:"currentHIDScriptSource"`
CurrentGadgetSettings *jsGadgetSettings `js:"currentGadgetSettings"`
EventLog *jsLoggerData `js:"eventLog"`
HidJobList *jsHidJobStateList `js:"hidJobList"`
IsModalEnabled bool `js:"isModalEnabled"`
Counter int `js:"count"`
@ -62,6 +63,7 @@ func createGlobalStateStruct() GlobalState {
state.CurrentGadgetSettings = NewUSBGadgetSettings()
//UpdateGadgetSettingsFromDeployed(state.CurrentGadgetSettings)
state.EventLog = NewLogger(maxLogEntries)
state.HidJobList = NewHIDJobStateList()
state.IsModalEnabled = false
state.Counter = 1337