github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/mappers/bluetooth_mapper/scheduler/scheduler.go (about)

     1  /*
     2  Copyright 2019 The KubeEdge Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8     http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package scheduler
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"strings"
    23  	"time"
    24  
    25  	"k8s.io/klog"
    26  
    27  	"github.com/kubeedge/kubeedge/mappers/bluetooth_mapper/action_manager"
    28  	"github.com/kubeedge/kubeedge/mappers/bluetooth_mapper/data_converter"
    29  	"github.com/kubeedge/kubeedge/mappers/bluetooth_mapper/helper"
    30  )
    31  
    32  const (
    33  	MapperTopicPrefix     = "$ke/device/bluetooth-mapper/"
    34  	SchedulerResultSuffix = "/scheduler/result"
    35  	defaultEventFrequency = 5000
    36  )
    37  
    38  // Schedule is structure to define a schedule
    39  type Schedule struct {
    40  	// Name is name of the schedule. It should be unique so that a stop-chan
    41  	// can be made corresponding to name to stop the schedule.
    42  	Name string `yaml:"name" json:"name"`
    43  	// Interval is the time in milliseconds after which this action are to be performed
    44  	Interval int `yaml:"interval" json:"interval"`
    45  	//OccurrenceLimit refers to the number of time the action can occur, if it is 0, then the  event will execute infinitely
    46  	OccurrenceLimit int `yaml:"occurrence-limit" json:"occurrence-limit"`
    47  	// Actions is list of Actions to be performed in this schedule
    48  	Actions []string `yaml:"actions"`
    49  }
    50  
    51  //Scheduler structure contains the list of schedules to be scheduled
    52  type Scheduler struct {
    53  	Schedules []Schedule `yaml:"schedules" json:"schedules"`
    54  }
    55  
    56  //ScheduleResult structure contains the format in which telemetry data will be published on the MQTT topic
    57  type ScheduleResult struct {
    58  	EventName   string
    59  	TimeStamp   int64
    60  	EventResult string
    61  }
    62  
    63  // ExecuteSchedule is responsible for scheduling the operations
    64  func (schedule *Schedule) ExecuteSchedule(actionManager []actionmanager.Action, dataConverter dataconverter.DataRead, deviceID string) {
    65  	klog.Infof("Executing schedule: %s", schedule.Name)
    66  	if schedule.OccurrenceLimit != 0 {
    67  		for iteration := 0; iteration < schedule.OccurrenceLimit; iteration++ {
    68  			schedule.performScheduleOperation(actionManager, dataConverter, deviceID)
    69  		}
    70  	} else {
    71  		for {
    72  			schedule.performScheduleOperation(actionManager, dataConverter, deviceID)
    73  		}
    74  	}
    75  	helper.ControllerWg.Done()
    76  }
    77  
    78  // performScheduleOperation is responsible for performing the operations associated with the schedule
    79  func (schedule *Schedule) performScheduleOperation(actionManager []actionmanager.Action, dataConverter dataconverter.DataRead, deviceID string) {
    80  	var scheduleResult ScheduleResult
    81  	actionExists := false
    82  	for _, actionName := range schedule.Actions {
    83  		for _, action := range actionManager {
    84  			if strings.EqualFold(action.Name, actionName) {
    85  				actionExists = true
    86  				klog.Infof("Performing scheduled operation: %s", action.Name)
    87  				action.PerformOperation(dataConverter)
    88  				scheduleResult.EventName = actionName
    89  				scheduleResult.TimeStamp = time.Now().UnixNano() / 1e6
    90  				scheduleResult.EventResult = fmt.Sprintf("%s", action.Operation.Value)
    91  				publishScheduleResult(scheduleResult, deviceID)
    92  			}
    93  		}
    94  		if schedule.Interval == 0 {
    95  			schedule.Interval = defaultEventFrequency
    96  		}
    97  		if !actionExists {
    98  			klog.Errorf("Action %s does not exist. Exiting from schedule !!!", actionName)
    99  			break
   100  		}
   101  		time.Sleep(time.Duration(time.Duration(schedule.Interval) * time.Millisecond))
   102  	}
   103  }
   104  
   105  //publishScheduleResult publishes the telemetry data on the given MQTT topic
   106  func publishScheduleResult(scheduleResult ScheduleResult, deviceID string) {
   107  	scheduleResultTopic := MapperTopicPrefix + deviceID + SchedulerResultSuffix
   108  	klog.Infof("Publishing schedule: %s result on topic: %s", scheduleResult.EventName, scheduleResultTopic)
   109  	scheduleResultBody, err := json.Marshal(scheduleResult)
   110  	if err != nil {
   111  		klog.Errorf("Error: %s", err)
   112  	}
   113  	helper.TokenClient = helper.Client.Publish(scheduleResultTopic, 0, false, scheduleResultBody)
   114  	if helper.TokenClient.Wait() && helper.TokenClient.Error() != nil {
   115  		klog.Errorf("client.publish() Error in device twin get  is %s", helper.TokenClient.Error())
   116  	}
   117  }