package com.xy.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xy.alipay.AliPay;
import com.xy.annotate.RestMappingController;
import com.xy.dto.DeviceBluetoothAuthDto;
import com.xy.dto.DeviceInfoDto;
import com.xy.dto.DeviceStatusDto;
import com.xy.dto.MercMiniDeviceDto;
import com.xy.dto.be.MercDto;
import com.xy.dto.common.MercLineDto;
import com.xy.dto.common.MercPlaceDto;
import com.xy.dto.mini.MiniMercRegionDto;
import com.xy.entity.*;
import com.xy.enums.MercStatus;
import com.xy.service.DeviceBluetoothAuthServiceImpl;
import com.xy.service.DeviceChargingServiceImpl;
import com.xy.service.DeviceInfoServiceImpl;
import com.xy.service.DeviceSysinfoServiceImpl;
import com.xy.service.be.MercFeignService;
import com.xy.service.common.MercLineService;
import com.xy.service.common.MercPlaceService;
import com.xy.utils.*;
import com.xy.utils.enums.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import static com.xy.utils.Beans.copy;
/**
*
* 小程序-设备
*
*
* @author hechunping
* @since 2023/3/4
*/
@RestMappingController("merc-mini/device")
@AllArgsConstructor
@Api(tags = "小程序-设备")
public class MercMiniDeviceController {
private final MercFeignService mercFeignService;
private final DeviceInfoServiceImpl deviceInfoService;
private final DeviceSysinfoServiceImpl deviceSysinfoService;
private final MercPlaceService mercPlaceService;
private final MercLineService mercLineService;
private final DeviceBluetoothAuthServiceImpl deviceBluetoothAuthService;
private final DeviceChargingServiceImpl deviceChargingService;
@ApiOperation("商户设备首页统计")
@PostMapping("mercHomeStatistical")
public R mercHomeStatistical(@RequestBody @Valid DeviceInfoDto.MercHomeQueryDTO dto) {
dto.setMercId(MercAuthUtils.getMercId());
dto.setMyDeviceIds(getMyDevices());
return deviceInfoService.mercHomeStatistical(dto);
}
@PostMapping("searchPage")
@ApiOperation("小程序商户设备搜索")
public R> mercDeviceSearchPage(@RequestBody DeviceInfoDto.Page page) {
page.setMercId(MercAuthUtils.getMercId());
page.setMyDeviceIds(getMyDevices());
return deviceInfoService.mercDeviceSearchPage(page);
}
@ApiOperation("小程序商户设备详情-设备信息")
@PostMapping("detail")
R detail(@RequestBody DeviceInfoDto.Obj obj) {
obj.setMercId(MercAuthUtils.getMercId());
obj.setIsStatus(true);
R r = deviceInfoService.obj(obj);
DeviceInfoDto.Vo vo = r.getData();
if (vo != null) {
//点位
Long placeId = vo.getPlaceId();
List merPlaceList = R.feignCheckData(mercPlaceService.list(new MercPlaceDto.ListDto().setIds(CollUtil.newArrayList(placeId))));
MercPlaceDto.Vo mercPlace = CollUtil.isNotEmpty(merPlaceList) ? merPlaceList.get(0) : null;
vo.setPlaceName(mercPlace == null ? StrUtil.EMPTY : mercPlace.getPlaceName());
//线路
Long placeLineId = vo.getPlaceLineId();
Map placeLineMap = R.feignCheckData(mercLineService.getNameList(new MercLineDto.GetNameListDto().setIds(CollUtil.newArrayList(placeLineId))));
vo.setPlaceLineName(CollUtil.isEmpty(placeLineMap) ? StrUtil.EMPTY : placeLineMap.get(placeLineId));
//区域
Long districtId = vo.getDistrictId();
Map districtMap = R.feignCheckData(mercPlaceService.merReginId2Name(new MiniMercRegionDto.IdList().setIds(CollUtil.newArrayList(districtId))));
vo.setDistrictName(CollUtil.isEmpty(districtMap) ? StrUtil.EMPTY : districtMap.get(districtId));
DeviceStatusDto.Vo deviceStatus = vo.getDeviceStatus();
vo.setNetStateName(deviceStatus == null ? StrUtil.EMPTY : DeviceNetSateType.getEnumByCode(deviceStatus.getNetState()).getDescription());
Integer deviceStateL = deviceStatus.getLockStateL();
Integer deviceStateR = deviceStatus.getLockStateR();
vo.setDeviceStateL(deviceStateL);
vo.setDeviceStateR(deviceStateR);
DeviceLockState deviceLockStateL = DeviceLockState.getEnumByCode(deviceStateL);
DeviceLockState deviceLockStateR = DeviceLockState.getEnumByCode(deviceStateR);
vo.setDeviceStateRName(deviceLockStateR == null ? "未知" : deviceLockStateR.getDescription());
vo.setDeviceStateLName(deviceLockStateL == null ? "未知" : deviceLockStateL.getDescription());
}
return R.ok(vo);
}
@ApiOperation("小程序商户设备详情-数据统计")
@PostMapping("dataCount")
R dataCount(@RequestBody DeviceInfoDto.DeviceDataCountDTO dto) {
dto.setMercId(MercAuthUtils.getMercId());
return deviceInfoService.dataCount(dto);
}
private R checkDeviceByMerc(DeviceInfo deviceInfo) {
Long mercId = MercAuthUtils.getMercId();
//商户是否已通过审核
MercDto.Vo mercInfo = mercFeignService.obj(new MercDto.ListDTO().setId(mercId)).getData();
if (!mercInfo.getStatus().equals(String.valueOf(MercStatus.APPROVED.getCode()))) {
return R.fail("商户未通过审核");
}
//设备是否存在
if (!Emptys.check(deviceInfo)) {
return R.fail("机器不存在");
}
//机器是否已授权给该商户
if (!deviceInfo.getMercId().equals(mercId)) {
return R.fail("机器未授权给商户");
}
//机器是否冻结
if (deviceInfo.getFreezeStatus().equals(Integer.valueOf(DictSonEnum.DEVICE_FREEZE_STATUS_2.getKey()))) {
return R.fail("机器已冻结");
}
return R.ok();
}
@PostMapping("isMerc")
@ApiOperation("判断设备是否归属商户")
public R isMerc(@RequestBody MercMiniDeviceDto.Active active) {
DeviceInfo deviceInfo = deviceInfoService.getById(active.getDeviceId());
R checkR = this.checkDeviceByMerc(deviceInfo);
if (checkR.getCode() == R.Enum.SUCCESS.getCode()) {
if (!deviceInfo.getActiveState().equals(Integer.valueOf(DictSonEnum.DEVICE_ACTIVE_STATUS_1.getKey()))) {
return R.fail("机器未激活");
}
return R.ok();
}
return checkR;
}
@PostMapping("getActiveInfo")
@ApiOperation("激活设备前判断")
public R getActiveInfo(@RequestBody MercMiniDeviceDto.Active active) {
DeviceInfo deviceInfo = deviceInfoService.getById(active.getDeviceId());
R checkR = this.checkDeviceByMerc(deviceInfo);
if (checkR.getCode() == R.Enum.SUCCESS.getCode()) {
if (deviceInfo.getActiveState().equals(Integer.valueOf(DictSonEnum.DEVICE_ACTIVE_STATUS_1.getKey()))) {
return R.fail("机器已激活");
}
return R.ok();
}
return checkR;
}
@PostMapping("active")
@ApiOperation("激活设备")
@Transactional(rollbackFor = Exception.class)
public R active(@RequestBody MercMiniDeviceDto.Active active) {
R activeInfo = this.getActiveInfo(active);
//激活设备
if (activeInfo.getCode() == R.Enum.SUCCESS.getCode()) {
DeviceInfo deviceInfo = deviceInfoService.getById(active.getDeviceId());
DeviceInfo updateDeviceInfo = new DeviceInfo()
.setDeviceId(active.getDeviceId())
.setActiveState(Integer.valueOf(DictSonEnum.DEVICE_ACTIVE_STATUS_1.getKey()))
.setBusyState(Integer.valueOf(DictSonEnum.DEVICE_BUSY_STATUS_1.getKey()))
.setActiveTime(LocalDateTime.now())
.setShowStatus(true);
//首次激活可使用x天
if (!deviceInfo.getIsChargingX()) {
SysDictRedis sysDictRedis = SysDictUtils.get(DictEnum.DEVICE_CHARGING.getKey(), DictSonEnum.DEVICE_CHARGING_X.getKey());
updateDeviceInfo.setIsChargingX(true)
.setChargingX(Integer.valueOf(sysDictRedis.getValue()));
}
deviceInfoService.updateById(updateDeviceInfo);
//添加设备计费
DeviceCharging deviceCharging = deviceChargingService.getById(deviceInfo.getDeviceId());
if (deviceCharging == null) {
LocalDateTime now = LocalDateTime.now();
deviceChargingService.save(new DeviceCharging()
.setDeviceId(deviceInfo.getDeviceId())
.setDeviceType(deviceInfo.getDeviceType())
.setTimeout(now)
.setCreateTime(now)
.setUpdateTime(now)
);
}
return R.ok();
} else {
return activeInfo;
}
}
@ApiOperation("运营状态修改")
@PostMapping("modifyBusyStage")
@AliPay(AliPay.Type.BUSY_STATE)
public R modifyBusyStage(@RequestBody @Validated MercMiniDeviceDto.BusySate busySate) {
Long mercId = MercAuthUtils.getMercId();
Long deviceId = busySate.getDeviceId();
DeviceInfo updateDeviceInfo = new DeviceInfo()
.setDeviceId(deviceId)
.setMercId(mercId)
.setBusyState(busySate.getBusyState());
deviceInfoService.updateById(updateDeviceInfo);
return R.ok();
}
@ApiOperation("修改设备信息、上传坐标等")
@PostMapping("updateInfo")
public R updateInfo(@RequestBody @Validated MercMiniDeviceDto.UpdateInfo dto) {
DeviceInfo deviceInfo = deviceInfoService.getById(dto.getDeviceId());
if (!Emptys.check(deviceInfo) || Objects.equals(deviceInfo.getDeviceId(), MercAuthUtils.getMercId())) {
return R.fail("设备不存在");
}
DeviceInfoDto.Update update = copy(DeviceInfoDto.Update.class, dto);
deviceInfoService.update(update);
return R.ok();
}
@ApiOperation("当前登录用户拥有的设备")
@PostMapping("myDevices")
R> myDevices() {
return R.ok(getMyDevices());
}
/**
* 获取登录人的设备
*
* @return
*/
List getMyDevices() {
boolean mercAdmin = MercAuthUtils.isMercAdmin();
Long mercId = MercAuthUtils.getMercId();
if (mercAdmin) {
List deviceInfos = deviceInfoService.list(Wrappers.lambdaQuery().eq(DeviceInfo::getMercId, mercId).eq(DeviceInfo::getActiveState, DeviceActiveStateEnum.TRUE.getCode()));
if (CollUtil.isEmpty(deviceInfos)) {
return CollUtil.newArrayList();
}
return deviceInfos.stream().map(DeviceInfo::getDeviceId).collect(Collectors.toList());
} else {
//成员设备
List deviceIds = R.feignCheckData(mercFeignService.mercUserDevice());
return deviceIds;
}
}
@PostMapping("genCode")
@ApiOperation("蓝牙开门-生成授权码")
public R genCode(@RequestBody @Validated DeviceBluetoothAuthDto.GenCode dto) {
String deviceSn = dto.getDeviceSn();
DeviceSysinfo deviceSysinfo = deviceSysinfoService.getOne(Wrappers.lambdaQuery().eq(DeviceSysinfo::getDeviceSn, deviceSn));
if (deviceSysinfo == null) {
return R.fail("设备不存在!");
}
Long deviceId = deviceSysinfo.getDeviceId();
//用户输入的
String authCode = dto.getAuthCode();
List myDevices = getMyDevices();
if (!myDevices.contains(deviceId)) {
return R.fail("抱歉!您无权对此设备进行授权!");
}
Long mercId = MercAuthUtils.getMercId();
DeviceBluetoothAuth deviceBluetoothAuth = deviceBluetoothAuthService.getOne(Wrappers.lambdaQuery()
.eq(DeviceBluetoothAuth::getDeviceId, deviceId)
.eq(DeviceBluetoothAuth::getMercId, mercId)
.eq(DeviceBluetoothAuth::getUseStatus, DeviceAuthCodeUseStatus.UN_USED.getCode())
);
String cacheAuthCode = getCacheAuthCode(deviceId);
if (deviceBluetoothAuth != null) {
if (StrUtil.isNotEmpty(cacheAuthCode)) {
return R.fail("此设备尚有未使用的授权码:【" + cacheAuthCode + "】,请使用后再来生成!");
} else {
//已失效了
deviceBluetoothAuthService.saveOrUpdate(deviceBluetoothAuth.setUseStatus(DeviceAuthCodeUseStatus.TIME_OUT.getCode()));
}
}
//缓存
setCacheAuthCode(deviceId, authCode);
DeviceBluetoothAuth saveInfo = new DeviceBluetoothAuth()
.setDeviceId(deviceId)
.setMercId(mercId)
.setDeviceId(deviceId).setAuthCode(authCode);
return R.ok(deviceBluetoothAuthService.save(saveInfo));
}
@PostMapping("verificationCode")
@ApiOperation("蓝牙开门-校验并使用授权码")
public R verificationCode(@RequestBody @Validated DeviceBluetoothAuthDto.VerificationCode dto) {
String deviceSn = dto.getDeviceSn();
DeviceSysinfo deviceSysinfo = deviceSysinfoService.getOne(Wrappers.lambdaQuery().eq(DeviceSysinfo::getDeviceSn, deviceSn));
if (deviceSysinfo == null) {
return R.fail("设备不存在!");
}
Long deviceId = deviceSysinfo.getDeviceId();
String authCode = dto.getAuthCode();
String cacheAuthCode = getCacheAuthCode(deviceId);
if (!authCode.equals(cacheAuthCode)) {
return R.fail("您输入的授权码有误或者无效!");
}
//验证通过,缓存去掉授权码,并更新状态
Long mercId = MercAuthUtils.getMercId();
DeviceBluetoothAuth deviceBluetoothAuth = deviceBluetoothAuthService.getOne(Wrappers.lambdaQuery()
.eq(DeviceBluetoothAuth::getDeviceId, deviceId)
.eq(DeviceBluetoothAuth::getAuthCode, authCode)
.eq(DeviceBluetoothAuth::getMercId, mercId)
.eq(DeviceBluetoothAuth::getUseStatus, DeviceAuthCodeUseStatus.UN_USED.getCode())
);
if (deviceBluetoothAuth == null) {
return R.fail("您输入的授权码无效!");
}
//缓存去掉授权码
delCacheAuthCode(deviceId);
deviceBluetoothAuth.setUseStatus(DeviceAuthCodeUseStatus.USED.getCode());
deviceBluetoothAuth.setUseUser(AuthorizeUtils.getLoginId(Long.class));
deviceBluetoothAuth.setUseTime(LocalDateTime.now());
return R.ok(deviceBluetoothAuthService.saveOrUpdate(deviceBluetoothAuth));
}
/**
* auth-code有效期30分钟,单位:s ,
*/
public static final Integer AUTH_CODE_TIMEOUT = 1800;
public static void setCacheAuthCode(Long deviceId, String code) {
RedisService redisService = SpringBeanUtils.getBean(RedisService.class);
redisService.set("device:auth:code:" + deviceId, code, AUTH_CODE_TIMEOUT);
}
public static String getCacheAuthCode(Long deviceId) {
RedisService redisService = SpringBeanUtils.getBean(RedisService.class);
return redisService.get("device:auth:code:" + deviceId);
}
public static void delCacheAuthCode(Long deviceId) {
RedisService redisService = SpringBeanUtils.getBean(RedisService.class);
redisService.remove("device:auth:code:" + deviceId);
}
}