push space left by uni-push
| | |
| | | downdoc = true |
| | | latestVersion = 1.0.0 |
| | | latestUrl = |
| | | juheweihaokey = 8c0efc4439080ef6c6aa2c29688c9550 |
| | | juheweihaokey = 8c0efc4439080ef6c6aa2c29688c9550 |
| | | pushAppId = WU8KzZBaTwADIjTwaMSzW5 |
| | | pushAppKey = 9JLs4B1ZVkAVh93JXX3MP4 |
| | | pushAppSecret = JuKr5y8IIC88WAWPicaSK3 |
| | | pushMasterSecret = IbSAe83ZoZAczhKSA3Bwj9 |
| | | pushPackageName = uni.UNI359F489 |
| | | pushSignature = BA:AD:09:3A:82:82:9F:B4:32:A7:B2:8C:B4:CC:F0:E9:F3:7D:AE:58 |
| | | pushBaseUrl = https://restapi.getui.com/v2/ |
| | |
| | | "car-service/extend/code" |
| | | "car-service/models" |
| | | "car-service/service" |
| | | "fmt" |
| | | "github.com/astaxie/beego" |
| | | "net/http" |
| | | "sort" |
| | | "sync" |
| | | "time" |
| | | ) |
| | | |
| | | type CarController struct { |
| | | beego.Controller |
| | | } |
| | | |
| | | //实时计算剩余车位数量,达到条件就推送 |
| | | func ComputeSpaceLeftRealTime() { |
| | | ticker := time.NewTicker(3 * time.Second) |
| | | prePushLeft := 0 |
| | | for { |
| | | select { |
| | | case <-ticker.C: |
| | | m := time.Now().Minute() |
| | | i := m % 10 |
| | | left := 80 |
| | | if i == 0 { |
| | | left = 10 |
| | | } |
| | | if m == 40 { |
| | | left = 5 |
| | | } |
| | | if left <=10 && left != prePushLeft { |
| | | go service.Push("育英智慧停车", fmt.Sprintf("当前剩余车位:%d个", left)) |
| | | } |
| | | updateSpaceLeft(left) |
| | | default: |
| | | time.Sleep(500 * time.Millisecond) |
| | | } |
| | | } |
| | | } |
| | | |
| | | var cacheSpaceLeft int |
| | | var cLock sync.RWMutex |
| | | func updateSpaceLeft(num int) { |
| | | cLock.Lock() |
| | | defer cLock.Unlock() |
| | | cacheSpaceLeft = num |
| | | } |
| | | func getSpaceLeft() int { |
| | | cLock.Lock() |
| | | defer cLock.Unlock() |
| | | return cacheSpaceLeft |
| | | } |
| | | |
| | | // @Title 统计剩余车位 |
| | |
| | | func (c *CarController) Statistic() { |
| | | //sv := service.NewCarService() |
| | | //sta := sv.Statistic() |
| | | m := time.Now().Minute() |
| | | i := m % 10 |
| | | left := 80 |
| | | if i == 0 { |
| | | left = 10 |
| | | } |
| | | if m == 40 { |
| | | left = 5 |
| | | } |
| | | left := getSpaceLeft() |
| | | sta := models.CarStatistic{ |
| | | Left: left, |
| | | } |
| | |
| | | CONTENT_TYPE_FORM = "application/x-www-form-urlencoded" |
| | | CONTENT_TYPE_MULFORM = "multipart/form-data" |
| | | CONTENT_TYPE_JSON = "application/json" |
| | | CONTENT_TYPE_UTF8_JSON = "application/json;charset=utf-8" |
| | | ) |
| | | |
| | | func DoPostRequest(url string, contentType string, body map[string]interface{}, params map[string]string, headers map[string]string) ([]byte, error) { |
| | |
| | | "crypto/md5" |
| | | "crypto/sha256" |
| | | "encoding/base64" |
| | | "encoding/hex" |
| | | "fmt" |
| | | "math/rand" |
| | | "strconv" |
| | | "strings" |
| | | "time" |
| | | "unsafe" |
| | | ) |
| | | |
| | | func Sha256(message string) string { |
| | | h := sha256.New() |
| | | h.Write([]byte(message)) |
| | | res := h.Sum(nil) |
| | | return hex.EncodeToString(res) |
| | | } |
| | | |
| | | func ComputeHmacSha256Base64(message string, secret string) string { |
| | | key := []byte(secret) |
| | | h := hmac.New(sha256.New, key) |
| | | h.Write([]byte(message)) |
| | | abs := h.Sum(nil) |
| | | |
| | | return base64.StdEncoding.EncodeToString(abs) |
| | | } |
| | | |
| | | |
| | | func Hik_ComputeSignatureBase64(appKey string, appSecret string, httpMethod string, accept string, contentType string, date string, url string) string { |
| | | httpHeaders := httpMethod +"\n" + accept + "\n" + contentType + "\n"+ date +"\n" |
| | |
| | | func MD5Base64(s []byte) string { |
| | | sum := md5.Sum(s) |
| | | return base64.StdEncoding.EncodeToString(sum[:]) |
| | | } |
| | | |
| | | func GenValidateCode(width int) string { |
| | | numeric := [10]byte{0,1,2,3,4,5,6,7,8,9} |
| | | r := len(numeric) |
| | | rand.Seed(time.Now().UnixNano()) |
| | | |
| | | var sb strings.Builder |
| | | for i := 0; i < width; i++ { |
| | | fmt.Fprintf(&sb, "%d", numeric[ rand.Intn(r) ]) |
| | | } |
| | | str := sb.String() |
| | | if strings.HasPrefix(str, "0") { |
| | | pI := RandInt(1,9) |
| | | str = strconv.Itoa(pI) + str[1:] |
| | | } |
| | | return str |
| | | } |
| | | |
| | | //生成区间随机数 |
| | | func RandInt(min, max int) int { |
| | | if min >= max || min ==0 ||max == 0 { |
| | | return max |
| | | } |
| | | return rand.Intn(max-min) + min |
| | | } |
| | |
| | | beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger" |
| | | } |
| | | controllers.Schedule() |
| | | go controllers.ComputeSpaceLeftRealTime() |
| | | beego.Run() |
| | | } |
| | |
| | | package service |
| | | |
| | | import ( |
| | | "fmt" |
| | | "testing" |
| | | ) |
| | | |
| | | func TestCarService_Statistic(t *testing.T) { |
| | | parkList := getHikParkList() |
| | | fmt.Println("parkList:", parkList) |
| | | |
| | | } |
New file |
| | |
| | | package service |
| | | |
| | | import ( |
| | | "car-service/extend/util" |
| | | "encoding/json" |
| | | "errors" |
| | | "fmt" |
| | | "github.com/astaxie/beego" |
| | | "sync" |
| | | "time" |
| | | ) |
| | | var latestToken *TokenResult |
| | | var lock sync.RWMutex |
| | | func getCacheToken() string { |
| | | lock.Lock() |
| | | defer lock.Unlock() |
| | | if latestToken != nil { |
| | | return latestToken.Token |
| | | } |
| | | return "" |
| | | } |
| | | func updateToken(newT *TokenResult) { |
| | | lock.Lock() |
| | | defer lock.Unlock() |
| | | latestToken = newT |
| | | } |
| | | |
| | | func init() { |
| | | newToken, err := RefreshToken() |
| | | if err == nil { |
| | | updateToken(newToken) |
| | | } |
| | | ticker := time.NewTicker(time.Hour * 20) |
| | | go func() { |
| | | for { |
| | | select { |
| | | case <-ticker.C: |
| | | if t,err := RefreshToken();err == nil { |
| | | updateToken(t) |
| | | } |
| | | default: |
| | | time.Sleep(time.Second * 5) |
| | | } |
| | | } |
| | | }() |
| | | } |
| | | |
| | | type PushResult struct { |
| | | Code int `json:"code"` |
| | | Msg string `json:"msg"` |
| | | Data interface{} `json:"data"` |
| | | } |
| | | |
| | | type TokenResult struct { |
| | | ExpireTime string `json:"expire_time"` |
| | | Token string `json:"token"` |
| | | } |
| | | |
| | | func Push(title string, msg string) (bool,error) { |
| | | appId := beego.AppConfig.String("pushAppId") |
| | | baseUrl := beego.AppConfig.String("pushBaseUrl") + appId |
| | | retryTimes := 0 |
| | | ReTry: |
| | | token := getCacheToken() |
| | | if token == "" { |
| | | return false, errors.New("token is nil") |
| | | } |
| | | url := baseUrl+"/push/all" |
| | | reqBody := map[string]interface{} { |
| | | "request_id": time.Now().Format("20060102150405") + util.GenValidateCode(6), |
| | | "settings":map[string]int { |
| | | "ttl": 8 * 3600 * 1000, |
| | | }, |
| | | "audience": "all", |
| | | "push_message": map[string]string{ |
| | | "title": title, |
| | | "body": msg, |
| | | "click_type": "url", |
| | | "url": "http://baidu.com", |
| | | }, |
| | | } |
| | | header := map[string]string { |
| | | "token": token, |
| | | } |
| | | b, err := util.DoPostRequest(url, util.CONTENT_TYPE_UTF8_JSON, reqBody, nil, header) |
| | | if err !=nil { |
| | | fmt.Println("DoPost err:", err) |
| | | return false, err |
| | | } |
| | | var result PushResult |
| | | err = json.Unmarshal(b, &result) |
| | | if err != nil { |
| | | fmt.Println("unmarshal err:", err) |
| | | return false, err |
| | | } |
| | | if result.Code == 0 { |
| | | return true, nil |
| | | } else if result.Code == 10001 { //token过期 |
| | | if retryTimes <=3 { |
| | | newToken, err := RefreshToken() |
| | | if err == nil { |
| | | updateToken(newToken) |
| | | retryTimes++ |
| | | goto ReTry |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | return false, errors.New("推送失败") |
| | | } |
| | | |
| | | func RefreshToken() (*TokenResult,error) { |
| | | //appId := beego.AppConfig.String("pushAppId") |
| | | //appKey := beego.AppConfig.String("pushAppKey") |
| | | //masterSecret := beego.AppConfig.String("pushMasterSecret") |
| | | //baseUrl := beego.AppConfig.String("pushBaseUrl") + appId |
| | | appId := "WU8KzZBaTwADIjTwaMSzW5" |
| | | appKey := "9JLs4B1ZVkAVh93JXX3MP4" |
| | | masterSecret := "IbSAe83ZoZAczhKSA3Bwj9" |
| | | baseUrl := "https://restapi.getui.com/v2/"+appId |
| | | url := baseUrl +"/auth" |
| | | timestamp := fmt.Sprintf("%v", time.Now().UnixNano() / 1e6) |
| | | sign := util.Sha256(appKey + timestamp + masterSecret) |
| | | reqBody := map[string]interface{} { |
| | | "sign": sign, |
| | | "timestamp": timestamp, |
| | | "appkey": appKey, |
| | | } |
| | | b, err := util.DoPostRequest(url, util.CONTENT_TYPE_UTF8_JSON, reqBody, nil, nil) |
| | | if err !=nil { |
| | | fmt.Println("DoPost err:", err) |
| | | return nil, err |
| | | } |
| | | var result PushResult |
| | | err = json.Unmarshal(b, &result) |
| | | if err != nil { |
| | | fmt.Println("unmarshal err:", err) |
| | | return nil, err |
| | | } |
| | | if result.Code == 0 { |
| | | db, err := json.Marshal(result.Data) |
| | | if err != nil { |
| | | fmt.Println("marshal err:", err) |
| | | return nil, err |
| | | } |
| | | var t TokenResult |
| | | err = json.Unmarshal(db, &t) |
| | | if err != nil { |
| | | fmt.Println("unmarshal err:", err) |
| | | return nil, err |
| | | } |
| | | return &t, nil |
| | | } |
| | | return nil, errors.New("获取unipush平台token失败") |
| | | } |
New file |
| | |
| | | package service |
| | | |
| | | import ( |
| | | "fmt" |
| | | "testing" |
| | | ) |
| | | |
| | | func TestRefreshToken(t *testing.T) { |
| | | r, err := RefreshToken() |
| | | fmt.Println(r, err) |
| | | } |