feiyu02
2022-11-15 027bf7da7a012fa36f8835b2419c74da8b2f1c28
2022.11.15
已添加4个文件
379 ■■■■■ 文件已修改
ledgerserver.rar 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/push/PushService.kt 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/timingtask/FetchVOC.kt 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/cn/flightfeather/supervision/timingtask/PushFume.kt 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ledgerserver.rar
Binary files differ
src/main/kotlin/cn/flightfeather/supervision/push/PushService.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,103 @@
package cn.flightfeather.supervision.push
import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase.getRequestId
import com.aliyuncs.push.model.v20160801.PushResponse
import com.aliyuncs.utils.ParameterHelper
import com.aliyuncs.push.model.v20160801.PushRequest
import com.aliyuncs.DefaultAcsClient
import com.aliyuncs.profile.DefaultProfile
import com.aliyuncs.profile.IClientProfile
import java.util.*
/**
 * ç§»åŠ¨æŽ¨é€æœåŠ¡
 * @author riku
 * Date: 2019/12/26
 */
class PushService {
    private val pushRequest: PushRequest
    private val client: DefaultAcsClient
    companion object {
        const val accessKeyId = "LTAI4FvmhG97saKL33tDqUV8"
        const val accessKeySecret = "3PyluVDS97GTGVmm1p3s6vbLkyqZMf"
        const val appKey = 28232249L
    }
    init {
        val profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret)
        client = DefaultAcsClient(profile)
        pushRequest = PushRequest()
        pushRequest.appKey = appKey
        pushRequest.pushType = "NOTICE" // æ¶ˆæ¯ç±»åž‹ MESSAGE NOTICE
        pushRequest.deviceType = "ANDROID" // è®¾å¤‡ç±»åž‹ ANDROID iOS ALL.
        setAndroid()
        // æŽ¨é€æŽ§åˆ¶
//        val pushDate = Date(System.currentTimeMillis()) // 30秒之间的时间点, ä¹Ÿå¯ä»¥è®¾ç½®æˆä½ æŒ‡å®šå›ºå®šæ—¶é—´
//        val pushTime = ParameterHelper.getISO8601Time(pushDate)
//        pushRequest.pushTime = pushTime // å»¶åŽæŽ¨é€ã€‚可选,如果不设置表示立即推送
        val expireTime = ParameterHelper.getISO8601Time(Date(System.currentTimeMillis() + 12 * 3600 * 1000)) // 12小时后消息失效, ä¸ä¼šå†å‘送
        pushRequest.expireTime = expireTime
        pushRequest.storeOffline = true // ç¦»çº¿æ¶ˆæ¯æ˜¯å¦ä¿å­˜,若保存, åœ¨æŽ¨é€æ—¶å€™ï¼Œç”¨æˆ·å³ä½¿ä¸åœ¨çº¿ï¼Œä¸‹ä¸€æ¬¡ä¸Šçº¿åˆ™ä¼šæ”¶åˆ°
    }
    fun pushByAccount(accountList: List<String>, all: Boolean = false) {
        // æŽ¨é€ç›®æ ‡
        val accounts = StringBuilder()
        accountList.forEach {
            if (accounts.isNotEmpty()) {
                accounts.append(",")
            }
            accounts.append(it)
        }
        if (all) {
            pushRequest.target = "ALL" //推送目标: DEVICE:按设备推送 ALIAS : æŒ‰åˆ«åæŽ¨é€ ACCOUNT:按帐号推送  TAG:按标签推送; ALL: å¹¿æ’­æŽ¨é€
            pushRequest.targetValue = "ALL" //根据Target来设定,如Target=DEVICE, åˆ™å¯¹åº”的值为 è®¾å¤‡id1,设备id2. å¤šä¸ªå€¼ä½¿ç”¨é€—号分隔.(帐号与设备有一次最多100个的限制)
        } else {
            pushRequest.target = "ACCOUNT" //推送目标: DEVICE:按设备推送 ALIAS : æŒ‰åˆ«åæŽ¨é€ ACCOUNT:按帐号推送  TAG:按标签推送; ALL: å¹¿æ’­æŽ¨é€
            pushRequest.targetValue = accounts.toString() //根据Target来设定,如Target=DEVICE, åˆ™å¯¹åº”的值为 è®¾å¤‡id1,设备id2. å¤šä¸ªå€¼ä½¿ç”¨é€—号分隔.(帐号与设备有一次最多100个的限制)
        }
        //        pushRequest.setTarget("ALL"); //推送目标: DEVICE:推送给设备; ACCOUNT:推送给指定帐号,TAG:推送给自定义标签; ALL: æŽ¨é€ç»™å…¨éƒ¨
//        pushRequest.setTargetValue("ALL"); //根据Target来设定,如Target=DEVICE, åˆ™å¯¹åº”的值为 è®¾å¤‡id1,设备id2. å¤šä¸ªå€¼ä½¿ç”¨é€—号分隔.(帐号与设备有一次最多100个的限制)
    }
    fun push(title: String, body: String) {
        // æŽ¨é€é…ç½®
        pushRequest.title = title // æ¶ˆæ¯çš„æ ‡é¢˜
        pushRequest.body = body // æ¶ˆæ¯çš„内容
        val pushResponse = client.getAcsResponse(pushRequest, true, 3)
        System.out.printf("RequestId: %s, MessageID: %s\n",
                pushResponse.requestId, pushResponse.messageId)
    }
    private fun setIOS() {
        // æŽ¨é€é…ç½®: iOS
        pushRequest.iosBadge = 5 // iOS应用图标右上角角标
        pushRequest.iosMusic = "default" // iOS通知声音
        pushRequest.iosSubtitle = "iOS10 subtitle"//iOS10通知副标题的内容
        pushRequest.iosNotificationCategory = "iOS10 Notification Category"//指定iOS10通知Category
        pushRequest.iosMutableContent = true//是否允许扩展iOS通知内容
        pushRequest.iosApnsEnv = "DEV"//iOS的通知是通过APNs中心来发送的,需要填写对应的环境信息。"DEV" : è¡¨ç¤ºå¼€å‘环境 "PRODUCT" : è¡¨ç¤ºç”Ÿäº§çŽ¯å¢ƒ
        pushRequest.iosRemind = true // æ¶ˆæ¯æŽ¨é€æ—¶è®¾å¤‡ä¸åœ¨çº¿ï¼ˆæ—¢ä¸Žç§»åŠ¨æŽ¨é€çš„æœåŠ¡ç«¯çš„é•¿è¿žæŽ¥é€šé“ä¸é€šï¼‰ï¼Œåˆ™è¿™æ¡æŽ¨é€ä¼šåšä¸ºé€šçŸ¥ï¼Œé€šè¿‡è‹¹æžœçš„APNs通道送达一次。注意:离线消息转通知仅适用于生产环境
        pushRequest.iosRemindBody = "iOSRemindBody"//iOS消息转通知时使用的iOS通知内容,仅当iOSApnsEnv=PRODUCT && iOSRemind为true时有效
        pushRequest.iosExtParameters = "{\"_ENV_\":\"DEV\",\"k2\":\"v2\"}" //通知的扩展属性(注意 : è¯¥å‚数要以json map的格式传入,否则会解析出错)
    }
    private fun setAndroid() {
        // æŽ¨é€é…ç½®: Android
        pushRequest.androidNotifyType = "BOTH"//通知的提醒方式 "VIBRATE" : éœ‡åЍ "SOUND" : å£°éŸ³ "BOTH" : å£°éŸ³å’Œéœ‡åЍ NONE : é™éŸ³
        pushRequest.androidNotificationChannel = "1"
//        pushRequest.androidNotificationBarType = 1//通知栏自定义样式0-100
//        pushRequest.androidNotificationBarPriority = 1//通知栏自定义样式0-100
        pushRequest.androidOpenType = "APPLICATION" //点击通知后动作 "APPLICATION" : æ‰“开应用 "ACTIVITY" : æ‰“å¼€AndroidActivity "URL" : æ‰“å¼€URL "NONE" : æ— è·³è½¬
//        pushRequest.androidOpenUrl = "http://www.aliyun.com" //Android收到推送后打开对应的url,仅当AndroidOpenType="URL"有效
//        pushRequest.androidActivity = "com.alibaba.push2.demo.XiaoMiPushActivity" // è®¾å®šé€šçŸ¥æ‰“开的activity,仅当AndroidOpenType="Activity"有效
        pushRequest.androidMusic = "default" // Android通知音乐
//        pushRequest.androidPopupActivity = "com.ali.demo.PopupActivity"//设置该参数后启动辅助弹窗功能, æ­¤å¤„指定通知点击后跳转的Activity(辅助弹窗的前提条件:1. é›†æˆç¬¬ä¸‰æ–¹è¾…助通道;2. StoreOffline参数设为true)
//        pushRequest.androidPopupTitle = "Popup Title"
//        pushRequest.androidPopupBody = "Popup Body"
//        pushRequest.androidExtParameters = "{\"k1\":\"android\",\"k2\":\"v2\"}" //设定通知的扩展属性。(注意 : è¯¥å‚数要以 json map çš„æ ¼å¼ä¼ å…¥,否则会解析出错)
    }
}
src/main/kotlin/cn/flightfeather/supervision/timingtask/FetchVOC.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
package cn.flightfeather.supervision.timingtask
import cn.flightfeather.supervision.common.net.VOCHttpService
import cn.flightfeather.supervision.domain.entity.DeviceInfo
import cn.flightfeather.supervision.domain.entity.VOCHourValue
import cn.flightfeather.supervision.domain.enumeration.DistrictType
import cn.flightfeather.supervision.domain.enumeration.SceneType
import cn.flightfeather.supervision.domain.mapper.DeviceInfoMapper
import cn.flightfeather.supervision.domain.mapper.VOCHourValueMapper
import cn.flightfeather.supervision.infrastructure.utils.DateUtil
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import tk.mybatis.mapper.entity.Example
import java.time.LocalDateTime
import java.util.*
import javax.annotation.PostConstruct
/**
 * èŽ·å–voc监测数据
 */
@Component
class FetchVOC : BaseTimingTask() {
    companion object {
        private lateinit var instance: FetchVOC
    }
    @Autowired
    lateinit var deviceInfoMapper: DeviceInfoMapper
    @Autowired
    lateinit var vocHourValueMapper: VOCHourValueMapper
    @PostConstruct
    fun init() {
        instance = this
    }
    override val period: Long
        get() = 15L
    override fun doTask(localtime:LocalDateTime) {
        getVOCData()
    }
    private fun getVOCData() {
        val deviceCodeList = mutableListOf<String>()
        deviceInfoMapper.selectByExample(Example(DeviceInfo::class.java).apply {
            createCriteria().andEqualTo("diProvinceCode", "31")
                .andEqualTo("diCityCode", "3100")
                .andEqualTo("diDistrictCode", DistrictType.XuHui.code)
                .andEqualTo("diSceneTypeId", SceneType.VehicleRepair.value)
                .andEqualTo("diDeviceTypeId", 1)
        }).forEach {
            it?.let {
                deviceCodeList.add(it.diCode)
            }
        }
        val cal = Calendar.getInstance(Locale.CHINA).apply {
            set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0)
        }
        val endTime = DateUtil.DateToString(cal.time, "yyyy-MM-dd HH:mm:ss") ?: ""
        cal.add(Calendar.HOUR_OF_DAY, -1)
        val startTime = DateUtil.DateToString(cal.time, "yyyy-MM-dd HH:mm:ss") ?: ""
        deviceCodeList.forEach {
            val deviceInfo = VOCHttpService.DeviceInfo(listOf(it), startTime, endTime)
//            threadPoo?.execute {
                VOCHttpService.getVOCData(deviceInfo)?.run {
                    try {
                        if (this["code"].asInt == 200) {
                            val data = this["data"].asJsonObject
                            data["rtdMinuteHourDayBeans"].asJsonArray.forEach {e ->
                                e.asJsonObject.let { o->
                                    val hourValue = VOCHourValue()
                                    hourValue.vocStatCode = o["deviceCode"].asString
                                    val collectTime = o["collectTime"].asString
                                    hourValue.vocDataTime = DateUtil.StringToDate(collectTime)
                                    o["minuteHourDayValueBeans"].asJsonArray.forEach {e1 ->
                                        e1.asJsonObject.let {o1 ->
                                            when (o1["factorCode"].asString) {
                                                "e70201" -> hourValue.vocFanElectricity1 = o1["factorAvg"].asDouble
                                                "e70202" -> hourValue.vocFanElectricity2 = o1["factorAvg"].asDouble
                                                "e70203" -> hourValue.vocFanElectricity3 = o1["factorAvg"].asDouble
                                                "e70204" -> hourValue.vocFanElectricity4 = o1["factorAvg"].asDouble
                                                "e70205" -> hourValue.vocFanElectricity5 = o1["factorAvg"].asDouble
                                                "e70206" -> hourValue.vocFanElectricity6 = o1["factorAvg"].asDouble
                                                "g29001" -> hourValue.vocValue = o1["factorAvg"].asDouble
                                            }
                                        }
                                    }
                                    val r = vocHourValueMapper.selectByExample(Example(VOCHourValue::class.java).apply {
                                        createCriteria().andEqualTo("vocDataTime", hourValue.vocDataTime)
                                                .andEqualTo("vocStatCode", it)
                                    })
                                    if (r.isEmpty()) {
                                        vocHourValueMapper.insertSelective(hourValue)
                                    }
                                }
                            }
                        }
                    } catch (e: Throwable) {
                        e.printStackTrace()
                    }
                }
//            }
        }
    }
}
src/main/kotlin/cn/flightfeather/supervision/timingtask/PushFume.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,163 @@
package cn.flightfeather.supervision.timingtask
import cn.flightfeather.supervision.common.net.FumeHttpService
import cn.flightfeather.supervision.domain.entity.DeviceInfo
import cn.flightfeather.supervision.domain.entity.FumeMinuteValue
import cn.flightfeather.supervision.domain.enumeration.DistrictType
import cn.flightfeather.supervision.domain.enumeration.SceneType
import cn.flightfeather.supervision.domain.mapper.DeviceInfoMapper
import cn.flightfeather.supervision.domain.mapper.FumeMinuteValueMapper
import cn.flightfeather.supervision.infrastructure.utils.DateUtil
import com.github.pagehelper.PageHelper
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import tk.mybatis.mapper.entity.Example
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.util.*
import javax.annotation.PostConstruct
import kotlin.math.round
/**
 * ä¸Šä¼ æ²¹çƒŸç›‘测数据
 */
@Component
class PushFume : BaseTimingTask() {
    companion object {
//        private lateinit var instance: PushFume
        val LOGGER = LoggerFactory.getLogger(PushFume::class.java)
    }
    @Autowired
    lateinit var deviceInfoMapper: DeviceInfoMapper
    @Autowired
    lateinit var fumeMinuteValueMapper: FumeMinuteValueMapper
//    @PostConstruct
//    fun init() {
//        instance = this
//    }
    private val deviceCodeList = mutableListOf<String>()
    override val period: Long
        get() = 1L
    override fun doTask(localtime: LocalDateTime) {
        LOGGER.info("===========开始执行油烟数据上传任务===============")
        // åˆ·æ–°ç›‘测点编号
        refreshDeviceCode()
        //每10分钟计算一次平均值并上传
        // FIXME: 2021/4/8 å‡å€¼çš„计算逻辑之后应该放到其他模块
        val min = localtime.minute
        if (min != 0 && min != 10 && min != 20 && min != 30 && min != 40 && min != 50) return
        //计算取值时间
        val endTime = Date.from(localtime.minusMinutes(1).withSecond(59).atZone(ZoneId.systemDefault()).toInstant())
        val startTime = Date.from(localtime.minusMinutes(10).withSecond(0).atZone(ZoneId.systemDefault()).toInstant())
        //生成上传数据结构体
        val postData = FumeHttpService.PostData()
        val allData = mutableListOf<FumeMinuteValue>()
        deviceCodeList.forEach {
            //获取前10分钟的数据
            val dataList = fumeMinuteValueMapper.selectByExample(Example(FumeMinuteValue::class.java).apply {
                createCriteria().andEqualTo("mvStatCode", it)
                        .andBetween("mvCreateTime", startTime, endTime)
                and(createCriteria().orIsNull("mvUpload")
                        .orEqualTo("mvUpload", false))
            })
            //计算均值
            var count = 0
            var total = 0.0
            dataList.forEach {
                total += it.mvFumeConcentration2
                if (it.mvFumeConcentration2 != 0.0) {
                    count++
                }
            }
            if (count == 0) {
                dataUpdate(dataList)
                return@forEach
            }
            val average = round(total / count * 100) / 100
            //均值等于0,不上报,直接更新上传状态
            if (average == 0.0) {
                dataUpdate(dataList)
                return@forEach
            }
            //生成上传数据结构体
            dataList.last().let {
                postData.data.add(FumeHttpService.FumeData(
                        "hengzhiyuan_${it.mvStatCode}",
                    DateUtil.DateToString(startTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS),
                        0.0, average,
                        if (it.mvFanStatus) 3 else 2,
                        it.mvFanElectricity, 0,
                        if (it.mvPurifierStatus) 3 else 2,
                        it.mvPurifierElectricity, 0,
                        0, 0.0
                ))
            }
            allData.addAll(dataList)
        }
        //上传数据并更新数据状态
        LOGGER.info("===========数据采样时间:$localtime")
        postData.data.forEach {
            LOGGER.info("${it.equipmentShowId}   **   ${it.dataTime}")
        }
        LOGGER.info("=================================")
        FumeHttpService.uploadData(postData)?.run {
            LOGGER.info(this.toString())
            if (this["code"].asInt == 0 && this["data"].asInt > 0) {
                dataUpdate(allData)
            }
            LOGGER.info("===========油烟数据上传任务结束============")
        }
    }
    /**
     * åˆ·æ–°ç›‘测点编号
     */
    @Synchronized
    private fun refreshDeviceCode() {
        val now = LocalDateTime.now()
        if (deviceCodeList.isEmpty() || (now.hour == 0 && now.minute <= period)) {
            deviceCodeList.clear()
            deviceInfoMapper.selectByExample(Example(DeviceInfo::class.java).apply {
                createCriteria().andEqualTo("diProvinceCode", "31")
                        .andEqualTo("diCityCode", "3100")
                        .andEqualTo("diDistrictCode", DistrictType.XuHui.code)
                        .andEqualTo("diSceneTypeId", SceneType.Restaurant.value)
                        .andEqualTo("diDeviceTypeId", 1)
                        .andEqualTo("diSupplier", "hengzhiyuan")
            }).forEach {
                it?.let {
                    deviceCodeList.add(it.diCode)
                }
            }
        }
    }
    /**
     * æ›´æ–°æ•°æ®çŠ¶æ€
     */
    private fun dataUpdate(dataList: List<FumeMinuteValue>) {
        dataList.forEach {
            it.mvUpload = true
            fumeMinuteValueMapper.updateByPrimaryKey(it)
        }
    }
}