# include "PhoneDevice.h"
# include <AndroidHelper.h>
# include <SpecData_JSON.h>
# include <Client/Terminal.h>
# include <Utils.h>
# include <LogThread.h>
# include "ncnn/yolov5ncnn.h"
# include "GPIOControl.h"
# include "CvText.h"
# include "PositionHelper.h"
# include "DngCreator.h"
# include <opencv2/opencv.hpp>
# include <opencv2/core.hpp>
# include <opencv2/imgproc.hpp>
# include <opencv2/core/types.hpp>
# include <opencv2/core/core.hpp>
# include <opencv2/imgproc/imgproc.hpp>
# include <android/log.h>
# include <android/thermal.h>
# include <android/imagedecoder.h>
# include <sys/system_properties.h>
# include <media/NdkImage.h>
# include <mat.h>
# include <string.h>
# ifdef USING_HDRPLUS
# include <hdrplus/hdrplus_pipeline.h>
# include <hdrplus2/include/HDRPlus.h>
# endif
# include "netcamera/netcamera.h"
# include <fcntl.h>
# include <filesystem>
# include <cstdio>
# include <unistd.h>
namespace fs = std : : filesystem ;
#if 0
# define CMD_SET_485_EN_STATE 131
# define CMD_SET_CAM_3V3_EN_STATE 132
# define CMD_SET_12V_EN_STATE 133
# endif
extern bool GetJniEnv ( JavaVM * vm , JNIEnv * * env , bool & didAttachThread ) ;
# define WAKELOCK_NAME "NDK_WK_"
// This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their
// ranges
// are normalized to eight bits.
static const int kMaxChannelValue = 262143 ;
class ByteArraysPointer
{
public :
ByteArraysPointer ( )
{
}
~ ByteArraysPointer ( )
{
# ifdef _DEBUG
ALOGD ( " ByteArray Size=%u " , ( uint32_t ) byteArrays . size ( ) ) ;
for ( auto it = byteArrays . cbegin ( ) ; it ! = byteArrays . cend ( ) ; + + it )
{
ALOGD ( " ByteArray Free: Size=%u " , ( uint32_t ) ( ( * it ) . size ( ) ) ) ;
}
# endif
byteArrays . clear ( ) ;
}
std : : vector < std : : vector < uint8_t > > byteArrays ;
} ;
cv : : Mat convert16bit2_8bit_ ( cv : : Mat ans ) {
if ( ans . type ( ) = = CV_16UC3 ) {
cv : : MatIterator_ < cv : : Vec3w > it , end ;
for ( it = ans . begin < cv : : Vec3w > ( ) , end = ans . end < cv : : Vec3w > ( ) ; it ! = end ; + + it )
{
// std::cout<<sizeof (*it)[0] <<std::endl;
( * it ) [ 0 ] * = ( 255.0 / USHRT_MAX ) ;
( * it ) [ 1 ] * = ( 255.0 / USHRT_MAX ) ;
( * it ) [ 2 ] * = ( 255.0 / USHRT_MAX ) ;
}
ans . convertTo ( ans , CV_8UC3 ) ;
} else if ( ans . type ( ) = = CV_16UC1 ) {
u_int16_t * ptr = ( u_int16_t * ) ans . data ;
int end = ans . rows * ans . cols ;
for ( int i = 0 ; i < end ; i + + ) {
* ( ptr + i ) * = ( 255.0 / USHRT_MAX ) ;
}
ans . convertTo ( ans , CV_8UC1 ) ;
} else {
// std::cout<<"Unsupported Data Type"<<std::endl;
}
return ans ;
}
char * MakeArgv ( const std : : string v )
{
char * argv = new char [ v . size ( ) + 1 ] ;
memset ( argv , 0 , v . size ( ) + 1 ) ;
strcpy ( argv , v . c_str ( ) ) ;
return argv ;
}
static long getFreeMemoryImpl ( const char * const sums [ ] , const size_t sumsLen [ ] , size_t num )
{
int fd = open ( " /proc/meminfo " , O_RDONLY | O_CLOEXEC ) ;
if ( fd < 0 ) {
ALOGW ( " Unable to open /proc/meminfo " ) ;
return - 1 ;
}
char buffer [ 2048 ] ;
const int len = read ( fd , buffer , sizeof ( buffer ) - 1 ) ;
close ( fd ) ;
if ( len < 0 ) {
ALOGW ( " Unable to read /proc/meminfo " ) ;
return - 1 ;
}
buffer [ len ] = 0 ;
size_t numFound = 0 ;
jlong mem = 0 ;
char * p = buffer ;
while ( * p & & numFound < num ) {
int i = 0 ;
while ( sums [ i ] ) {
if ( strncmp ( p , sums [ i ] , sumsLen [ i ] ) = = 0 ) {
p + = sumsLen [ i ] ;
while ( * p = = ' ' ) p + + ;
char * num = p ;
while ( * p > = ' 0 ' & & * p < = ' 9 ' ) p + + ;
if ( * p ! = 0 ) {
* p = 0 ;
p + + ;
if ( * p = = 0 ) p - - ;
}
mem + = atoll ( num ) * 1024 ;
numFound + + ;
break ;
}
i + + ;
}
p + + ;
}
return numFound > 0 ? mem : - 1 ;
}
static jlong android_os_Process_getFreeMemory ( )
{
static const char * const sums [ ] = { " MemFree: " , " Cached: " , NULL } ;
static const size_t sumsLen [ ] = { strlen ( " MemFree: " ) , strlen ( " Cached: " ) , 0 } ;
return getFreeMemoryImpl ( sums , sumsLen , 2 ) ;
}
static jlong android_os_Process_getTotalMemory ( )
{
static const char * const sums [ ] = { " MemTotal: " , NULL } ;
static const size_t sumsLen [ ] = { strlen ( " MemTotal: " ) , 0 } ;
return getFreeMemoryImpl ( sums , sumsLen , 1 ) ;
}
static inline uint32_t YUV2RGB ( int nY , int nU , int nV ) {
nY - = 16 ;
nU - = 128 ;
nV - = 128 ;
if ( nY < 0 ) nY = 0 ;
// This is the floating point equivalent. We do the conversion in integer
// because some Android devices do not have floating point in hardware.
// nR = (int)(1.164 * nY + 1.596 * nV);
// nG = (int)(1.164 * nY - 0.813 * nV - 0.391 * nU);
// nB = (int)(1.164 * nY + 2.018 * nU);
int nR = ( int ) ( 1192 * nY + 1634 * nV ) ;
int nG = ( int ) ( 1192 * nY - 833 * nV - 400 * nU ) ;
int nB = ( int ) ( 1192 * nY + 2066 * nU ) ;
nR = std : : min ( kMaxChannelValue , std : : max ( 0 , nR ) ) ;
nG = std : : min ( kMaxChannelValue , std : : max ( 0 , nG ) ) ;
nB = std : : min ( kMaxChannelValue , std : : max ( 0 , nB ) ) ;
nR = ( nR > > 10 ) & 0xff ;
nG = ( nG > > 10 ) & 0xff ;
nB = ( nB > > 10 ) & 0xff ;
return 0xff000000 | ( nR < < 16 ) | ( nG < < 8 ) | nB ;
}
class AutoEnv
{
public :
AutoEnv ( JavaVM * vm )
{
didAttachThread = false ;
env = NULL ;
m_vm = vm ;
jboolean ret = JNI_FALSE ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
}
}
~ AutoEnv ( )
{
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
}
private :
JavaVM * m_vm ;
JNIEnv * env ;
bool didAttachThread ;
} ;
CPhoneDevice : : CPhoneCamera : : CPhoneCamera ( CPhoneDevice * dev , int32_t width , int32_t height , const NdkCamera : : CAMERA_PARAMS & params ) : NdkCamera ( width , height , params ) , m_dev ( dev )
{
}
CPhoneDevice : : CPhoneCamera : : ~ CPhoneCamera ( )
{
m_dev = NULL ;
}
bool CPhoneDevice : : CPhoneCamera : : on_image ( cv : : Mat & rgb )
{
if ( m_dev ! = NULL )
{
return m_dev - > OnImageReady ( rgb ) ;
}
return false ;
}
bool CPhoneDevice : : CPhoneCamera : : onOneCapture ( std : : shared_ptr < ACameraMetadata > characteristics , std : : shared_ptr < ACameraMetadata > result , uint32_t ldr , uint32_t duration , cv : : Mat rgb )
{
if ( m_dev ! = NULL )
{
return m_dev - > onOneCapture ( characteristics , result , ldr , duration , rgb ) ;
}
return false ;
}
bool CPhoneDevice : : CPhoneCamera : : onBurstCapture ( std : : shared_ptr < ACameraMetadata > characteristics , std : : vector < std : : shared_ptr < ACameraMetadata > > & results , uint32_t ldr , uint32_t duration , std : : vector < std : : vector < uint8_t > > & frames )
{
if ( m_dev ! = NULL )
{
return m_dev - > onBurstCapture ( characteristics , results , ldr , duration , frames ) ;
}
return false ;
}
bool CPhoneDevice : : CPhoneCamera : : onBurstCapture ( std : : shared_ptr < ACameraMetadata > characteristics , std : : vector < std : : shared_ptr < ACameraMetadata > > & results , uint32_t ldr , uint32_t duration , std : : vector < std : : shared_ptr < AImage > > & frames )
{
if ( m_dev ! = NULL )
{
return m_dev - > onBurstCapture ( characteristics , results , ldr , duration , frames ) ;
}
return false ;
}
void CPhoneDevice : : CPhoneCamera : : on_error ( const std : : string & msg )
{
if ( m_dev ! = NULL )
{
m_dev - > onError ( msg ) ;
}
}
void CPhoneDevice : : CPhoneCamera : : onDisconnected ( ACameraDevice * device )
{
if ( m_dev ! = NULL )
{
m_dev - > onDisconnected ( device ) ;
}
}
CPhoneDevice : : CJpegCamera : : CJpegCamera ( CPhoneDevice * dev , int32_t width , int32_t height , const std : : string & path , const NdkCamera : : CAMERA_PARAMS & params ) : CPhoneDevice : : CPhoneCamera ( dev , width , height , params ) , m_path ( path )
{
}
bool CPhoneDevice : : CJpegCamera : : onOneCapture ( std : : shared_ptr < ACameraMetadata > characteristics , std : : shared_ptr < ACameraMetadata > result , uint32_t ldr , uint32_t duration , cv : : Mat rgb )
{
if ( m_dev ! = NULL )
{
return m_dev - > onOneCapture ( characteristics , result , ldr , duration , rgb ) ;
}
return false ;
}
bool CPhoneDevice : : CJpegCamera : : onBurstCapture ( std : : shared_ptr < ACameraMetadata > characteristics , std : : vector < std : : shared_ptr < ACameraMetadata > > & results , uint32_t ldr , uint32_t duration , std : : vector < std : : vector < uint8_t > > & frames )
{
if ( m_dev ! = NULL )
{
m_dev - > onBurstCapture ( characteristics , results , ldr , duration , frames ) ;
}
return true ;
}
bool CPhoneDevice : : CJpegCamera : : onBurstCapture ( std : : shared_ptr < ACameraMetadata > characteristics , std : : vector < std : : shared_ptr < ACameraMetadata > > & results , uint32_t ldr , uint32_t duration , std : : vector < std : : shared_ptr < AImage > > & frames )
{
if ( m_dev ! = NULL )
{
m_dev - > onBurstCapture ( characteristics , results , ldr , duration , frames ) ;
}
return true ;
}
void CPhoneDevice : : CJpegCamera : : onImageAvailable ( AImageReader * reader )
{
ALOGD ( " onImageAvailable %p " , reader ) ;
AImage * image = 0 ;
media_status_t mstatus = AImageReader_acquireLatestImage ( reader , & image ) ;
if ( mstatus ! = AMEDIA_OK )
{
// error
// https://stackoverflow.com/questions/67063562
if ( mstatus ! = AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE )
{
XYLOG ( XYLOG_SEVERITY_ERROR , " AImageReader_acquireLatestImage error: %d " , mstatus ) ;
}
return ;
}
uint8_t * y_data = 0 ;
int y_len = 0 ;
#if 0
if ( ! lightDetected )
{
AImage_getPlaneData ( image , 0 , & y_data , & y_len ) ;
lightDetected = true ;
# if __cplusplus >= 201703L
uint64_t avgY = std : : reduce ( y_data , y_data + y_len , 0 ) ;
# else
uint64_t avgY = std : : accumulate ( y_data , y_data + y_len , 0 ) ;
# endif
avgY = avgY / ( uint64_t ) y_len ;
mLdr = avgY ;
# if 1
if ( avgY < 50 )
{
if ( m_params . autoExposure )
{
uint8_t aeMode = ACAMERA_CONTROL_AE_MODE_OFF ;
camera_status_t status = ACaptureRequest_setEntry_u8 ( capture_request , ACAMERA_CONTROL_AE_MODE , 1 , & aeMode ) ;
int32_t sensitivity = ( avgY < 5 ) ? 2000 : ( mResult . sensitivity * 60.0 / avgY ) ;
status = ACaptureRequest_setEntry_i32 ( capture_request , ACAMERA_SENSOR_SENSITIVITY , 1 , & sensitivity ) ;
int64_t exposureTime = ( avgY < 5 ) ? 200 * 1000000 : ( mResult . exposureTime * 120.0 / avgY ) ;
status = ACaptureRequest_setEntry_i64 ( capture_request , ACAMERA_SENSOR_EXPOSURE_TIME , 1 , & exposureTime ) ;
XYLOG ( XYLOG_SEVERITY_WARNING , " YUV Light: %u EXPO:%lld => %lld ISO: %u => %u " , ( uint32_t ) avgY ,
mResult . exposureTime , exposureTime , mResult . sensitivity , sensitivity ) ;
}
AImage_delete ( image ) ;
return ;
}
# endif
}
# endif
int32_t format ;
AImage_getFormat ( image , & format ) ;
if ( format = = AIMAGE_FORMAT_JPEG )
{
int planeCount ;
media_status_t status = AImage_getNumberOfPlanes ( image , & planeCount ) ;
// LOGI("Info: getNumberOfPlanes() planeCount = %d", planeCount);
if ( ! ( status = = AMEDIA_OK & & planeCount = = 1 ) )
{
// LOGE("Error: getNumberOfPlanes() planeCount = %d", planeCount);
return ;
}
uint8_t * data = nullptr ;
int len = 0 ;
AImage_getPlaneData ( image , 0 , & data , & len ) ;
FILE * file = fopen ( m_path . c_str ( ) , " wb " ) ;
if ( file & & data & & len )
{
fwrite ( data , 1 , len , file ) ;
fclose ( file ) ;
}
else
{
if ( file )
fclose ( file ) ;
}
}
AImage_delete ( image ) ;
}
int32_t CPhoneDevice : : CJpegCamera : : getOutputFormat ( ) const
{
return AIMAGE_FORMAT_JPEG ;
}
CPhoneDevice : : CPhoneDevice ( JavaVM * vm , jobject service , const std : : string & appPath , unsigned int netId , unsigned int versionCode , const std : : string & nativeLibDir )
: mVersionCode ( versionCode ) , m_nativeLibraryDir ( nativeLibDir ) , m_network ( NULL ) , m_netHandle ( NETWORK_UNSPECIFIED )
{
mCamera = NULL ;
m_listener = NULL ;
m_pRecognizationCfg = NULL ;
mAIInitialized = false ;
mHeartbeatStartTime = 0 ;
mHeartbeatDuration = 0 ;
m_javaService = NULL ;
m_appPath = appPath ;
mNetId = netId ;
m_signalLevel = 0 ;
m_signalLevelUpdateTime = time ( NULL ) ;
mBuildTime = 0 ;
m_cameraStatus = false ;
m_sensorsStatus = false ;
m_lastTime = 0 ;
m_shouldStopWaiting = false ;
m_collecting = false ;
RegisterHandlerForSignal ( SIGUSR2 ) ;
GpioControl : : Startup ( ) ;
LoadNetworkInfo ( ) ;
m_vm = vm ;
JNIEnv * env = NULL ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
}
if ( service ! = NULL )
{
m_javaService = env - > NewGlobalRef ( service ) ;
jclass classService = env - > GetObjectClass ( m_javaService ) ;
mRegisterHeartbeatMid = env - > GetMethodID ( classService , " registerHeartbeatTimer " , " (IJ)V " ) ;
mUpdateTimeMid = env - > GetMethodID ( classService , " updateTime " , " (J)Z " ) ;
mUpdateCaptureScheduleMid = env - > GetMethodID ( classService , " updateCaptureSchedule " , " (J)Z " ) ;
mStartRecordingMid = env - > GetMethodID ( classService , " startRecording " , " (ZIJIIIIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V " ) ;
mRequestWakelockMid = env - > GetMethodID ( classService , " requestWakelock " , " (Ljava/lang/String;J)V " ) ;
mReleaseWakelockMid = env - > GetMethodID ( classService , " releaseWakelock " , " (Ljava/lang/String;)V " ) ;
mGetSystemInfoMid = env - > GetMethodID ( classService , " getSystemInfo " , " ()Ljava/lang/String; " ) ;
mInstallAppMid = env - > GetMethodID ( classService , " installApp " , " (Ljava/lang/String;J)Z " ) ;
mRebootMid = env - > GetMethodID ( classService , " reboot " , " (IJLjava/lang/String;)V " ) ;
mEnableGpsMid = env - > GetMethodID ( classService , " enableGps " , " (Z)V " ) ;
mRequestPositionMid = env - > GetMethodID ( classService , " requestPosition " , " ()Z " ) ;
mExecHdrplusMid = env - > GetMethodID ( classService , " execHdrplus " , " (IILjava/lang/String;Ljava/lang/String;)I " ) ;
mSetStaticIpMid = env - > GetMethodID ( classService , " setStaticNetwork " , " (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V " ) ;
mCallSysCameraMid = env - > GetMethodID ( classService , " callSystemCamera " , " (IJ)V " ) ;
env - > DeleteLocalRef ( classService ) ;
}
if ( didAttachThread )
{
vm - > DetachCurrentThread ( ) ;
}
m_timerUidFeed = time ( NULL ) * 1000 ;
m_wakelockIdFeed = ( unsigned long ) m_timerUidFeed ;
m_uniqueIdFeed = ( unsigned long ) m_timerUidFeed ;
# ifdef USING_NRSEC
GpioControl : : setCam3V3Enable ( true ) ;
GpioControl : : setSpiPower ( true ) ;
# endif
}
CPhoneDevice : : ~ CPhoneDevice ( )
{
m_devLocker . lock ( ) ;
for ( auto it = mTimers . begin ( ) ; it ! = mTimers . end ( ) ; + + it )
{
timer_delete ( ( timer_t ) it - > first ) ;
delete it - > second ;
}
mTimers . clear ( ) ;
m_devLocker . unlock ( ) ;
JNIEnv * env = NULL ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
}
env - > DeleteGlobalRef ( m_javaService ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
m_javaService = NULL ;
if ( m_pRecognizationCfg ! = NULL )
{
if ( mAIInitialized )
{
ncnn_uninit ( ) ;
}
m_pRecognizationCfg = NULL ;
}
if ( m_network ! = NULL )
{
delete m_network ;
m_network = NULL ;
}
GpioControl : : Stop ( ) ;
}
void CPhoneDevice : : SetListener ( IListener * listener )
{
m_listener = listener ;
}
void CPhoneDevice : : SetRecognizationCfg ( const IDevice : : CFG_RECOGNIZATION * pRecognizationCfg )
{
if ( m_pRecognizationCfg = = NULL & & pRecognizationCfg ! = NULL & & ( pRecognizationCfg - > enabled ! = 0 ) )
{
// TODO
std : : string paramFile = m_appPath + ( APP_PATH_RECOG_PARAM ) ;
std : : string binFile = m_appPath + ( APP_PATH_RECOG_BIN ) ;
std : : error_code err ;
if ( ! existsFile ( paramFile ) | | ! existsFile ( binFile ) | | fs : : is_directory ( fs : : path ( paramFile ) , err ) | | fs : : is_directory ( fs : : path ( binFile ) , err ) )
{
XYLOG ( XYLOG_SEVERITY_WARNING , " AI Config Files are invalid " ) ;
}
else
{
XYLOG ( XYLOG_SEVERITY_INFO , " AI Enabled and will Init NCNN " ) ;
ncnn_init ( ) ;
mAIInitialized = true ;
bool res = YoloV5Ncnn_Init ( paramFile , binFile ) ;
if ( res )
{
XYLOG ( XYLOG_SEVERITY_INFO , " Succeeded to Init NCNN " ) ;
}
else
{
XYLOG ( XYLOG_SEVERITY_ERROR , " Failed to Init NCNN " ) ;
}
}
}
else
{
XYLOG ( XYLOG_SEVERITY_WARNING , " AI Disabled " ) ;
}
m_pRecognizationCfg = pRecognizationCfg ;
}
bool CPhoneDevice : : BindNetwork ( int sock )
{
return true ;
}
bool CPhoneDevice : : SelfTest ( std : : string & result )
{
result . clear ( ) ;
const char * ITEM_SEP = " \t " ; //
unsigned int numberOfChannels = 0 ;
result + = " 设备自检 版本: " + GetVersion ( ) + ITEM_SEP ;
Json : : Value appConfig = Json : : objectValue ;
std : : vector < unsigned char > content ;
std : : string filePath = m_appPath + ( APP_DATA_DIR DIR_SEP_STR APP_FILE_NAME_APP_CONF ) ;
if ( ! readFile ( filePath , content ) )
{
result + = " 读取系统配置文件App.json失败 " ;
result + = ITEM_SEP ;
}
else
{
Json : : CharReaderBuilder builder ;
std : : unique_ptr < Json : : CharReader > reader ( builder . newCharReader ( ) ) ;
const char * doc = ( const char * ) & ( content [ 0 ] ) ;
if ( reader - > parse ( doc , doc + content . size ( ) , & appConfig , NULL ) )
{
unsigned int val = 0 ;
if ( GetJSONUInt32Value ( appConfig , " channels " , val ) & & ( val > 0 & & val < = 255 ) )
{
numberOfChannels = val ;
result + = " 通道数: " + std : : to_string ( numberOfChannels ) + ITEM_SEP ;
}
else
{
result + = " 通道数未定义或者无效 " + std : : string ( ITEM_SEP ) ;
}
}
else
{
result + = " 解析系统配置文件App.json失败 " + std : : string ( ITEM_SEP ) ;
}
}
for ( unsigned int channel = 1 ; channel < = numberOfChannels ; channel + + )
{
std : : string path = m_appPath + ( APP_PATH_CHANNELS DIR_SEP_STR ) ;
unsigned char cameraId = 0 ;
unsigned char usbCamera = 0 ;
Json : : Value channelCfg = Json : : objectValue ;
content . clear ( ) ;
filePath = m_appPath + ( APP_DATA_DIR DIR_SEP_STR APP_FILE_NAME_APP_CONF ) ;
if ( ! readFile ( filePath , content ) )
{
result + = " 读取通道 " + std : : to_string ( channel ) + " 配置文件失败 " + std : : string ( ITEM_SEP ) ;
}
else
{
Json : : CharReaderBuilder builder ;
std : : unique_ptr < Json : : CharReader > reader ( builder . newCharReader ( ) ) ;
const char * doc = ( const char * ) & ( content [ 0 ] ) ;
if ( reader - > parse ( doc , doc + content . size ( ) , & channelCfg , NULL ) )
{
GetJSONUInt8Value ( channelCfg , " usbCamera " , usbCamera ) ;
if ( GetJSONUInt8Value ( channelCfg , " cameraId " , cameraId ) )
{
result + = " 通道 " + std : : to_string ( channel ) + " Camera ID为 " + std : : to_string ( cameraId ) + ITEM_SEP ;
}
else
{
cameraId = channel - 1 ;
result + = " 通道 " + std : : to_string ( channel ) + " 未定义Camera ID, 使用默认值 " + std : : to_string ( cameraId ) + ITEM_SEP ;
}
}
else
{
result + = " 解析通道 " + std : : to_string ( channel ) + " 配置文件App.json失败 " + std : : string ( ITEM_SEP ) ;
}
}
int32_t width = 0 ;
int32_t height = 0 ;
NdkCamera : : CAMERA_PARAMS params = { 0 } ;
params . burstCaptures = 1 ;
if ( usbCamera )
{
GpioControl : : setOtgState ( true ) ;
}
GpioControl : : setCam3V3Enable ( true ) ;
NdkCamera camera ( width , height , params ) ;
int res = camera . selfTest ( std : : to_string ( cameraId ) , width , height ) ;
GpioControl : : setCam3V3Enable ( false ) ;
if ( usbCamera )
{
GpioControl : : setOtgState ( false ) ;
}
if ( res = = 0 )
{
result + = " 通道 " + std : : to_string ( channel ) + " 正常:最大分辨率: " + std : : to_string ( width ) + " x " + std : : to_string ( height ) + ITEM_SEP ;
}
else
{
result + = " 通道 " + std : : to_string ( channel ) + " 异常 err= " + std : : to_string ( res ) + ITEM_SEP ;
}
}
int bv = QueryBatteryVoltage ( DEFAULT_BATTERY_QUERY_RETRIES ) ;
if ( bv > 0 )
{
bv - = bv % 100 ;
result + = std : : string ( " 电池电压: " ) + std : : to_string ( bv / 1000 ) + std : : string ( " . " ) + std : : to_string ( ( bv % 1000 ) / 100 ) + ITEM_SEP ;
}
fs : : space_info si = fs : : space ( " /data " ) ;
double fr = ( ( double ) si . available * 100.0f ) / ( ( double ) si . capacity ) ;
result + = " 可用存储: " ;
result + = std : : to_string ( ( int ) fr ) ;
result + = " %% " + std : : string ( ITEM_SEP ) ;
long fm = android_os_Process_getFreeMemory ( ) ;
long tm = android_os_Process_getTotalMemory ( ) ;
double fmp = ( ( double ) fm * 100.0f ) / ( ( double ) tm ) ;
result + = std : : string ( " 可用内存: " ) + std : : to_string ( ( int ) fmp ) + std : : string ( " %% " ) + ITEM_SEP ;
if ( ! m_tfCardPath . empty ( ) )
{
fs : : space_info si2 = fs : : space ( m_tfCardPath . c_str ( ) ) ;
double fr2 = ( ( double ) si2 . available * 100.0f ) / ( ( double ) si2 . capacity ) ;
result + = " TF卡可用空间: " ;
result + = std : : to_string ( ( int ) fr2 ) ;
result + = " %% " + std : : string ( ITEM_SEP ) ;
}
result + = " 4G信号强度: " ;
result + = std : : to_string ( m_signalLevel ) ;
result + = ITEM_SEP ;
result + = " 网络接口: " ;
std : : vector < std : : string > devices ;
GetNetDevices ( devices ) ;
for ( auto it = devices . cbegin ( ) ; it ! = devices . cend ( ) ; + + it )
{
result + = ( * it ) ;
result + = " " ;
}
// result += ITEM_SEP;
return true ;
}
bool CPhoneDevice : : UpdateTime ( time_t ts )
{
JNIEnv * env = NULL ;
jboolean ret = JNI_FALSE ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
}
jlong timeInMillis = ( ( jlong ) ts ) * 1000 ;
ret = env - > CallBooleanMethod ( m_javaService , mUpdateTimeMid , timeInMillis ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
return ( ret = = JNI_TRUE ) ;
}
bool CPhoneDevice : : UpdateSchedules ( )
{
JNIEnv * env = NULL ;
jboolean ret = JNI_FALSE ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
}
time_t ts = time ( NULL ) ;
ret = env - > CallBooleanMethod ( m_javaService , mUpdateCaptureScheduleMid , ts ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
return ( ret = = JNI_TRUE ) ;
}
int CPhoneDevice : : QueryBatteryVoltage ( int retries )
{
int val = - 1 ; // // BatVol
for ( int idx = 0 ; idx < retries ; idx + + )
{
val = GpioControl : : getBatteryBusVoltage ( ) ; // // BatVol
if ( val > = 0 )
{
break ;
}
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 10 ) ) ;
}
return val ;
}
bool CPhoneDevice : : QuerySystemProperties ( std : : map < std : : string , std : : string > & properties )
{
char value [ PROP_VALUE_MAX ] = { 0 } ;
std : : map < std : : string , std : : string > powerInfo ;
int res = 0 ;
int bv = - 1 ;
for ( std : : map < std : : string , std : : string > : : iterator it = properties . begin ( ) ; it ! = properties . end ( ) ; + + it )
{
if ( ! ( it - > second . empty ( ) ) )
{
continue ;
}
if ( it - > first = = PROP_EQUIP_NAME )
{
__system_property_get ( " ro.product.name " , value ) ;
it - > second = value ;
}
else if ( it - > first = = PROP_MODEL )
{
__system_property_get ( " ro.product.model " , value ) ;
it - > second = std : : string ( value ) ;
}
else if ( it - > first = = PROP_BS_MANU )
{
__system_property_get ( " ro.product.manufacturer " , value ) ;
it - > second = std : : string ( value ) ;
}
else if ( it - > first = = PROP_VERSION )
{
// FOR Protocol
snprintf ( value , sizeof ( value ) , " %u.%03u " , ( mVersionCode / 1000 ) , ( mVersionCode % 1000 ) ) ;
// __system_property_get("ro.build.version.release", value);
it - > second = std : : string ( value ) ;
}
else if ( it - > first = = ( PROP_VERSION_ABBR ) )
{
// FOR OSD
string version = GetVersion ( ) ;
#if 0
version + = " " + FormatLocalTime ( mBuildTime ) ;
# endif
it - > second = version ;
}
else if ( it - > first = = PROP_BUILD_TIME )
{
it - > second = FormatLocalDateTime ( mBuildTime ) ;
}
else if ( it - > first = = PROP_PROD_DATE )
{
__system_property_get ( " ro.build.date.utc " , value ) ;
it - > second = std : : string ( value ) ;
}
else if ( it - > first = = PROP_SN | | it - > first = = PROP_BS_ID )
{
__system_property_get ( " ro.serialno " , value ) ;
it - > second = std : : string ( value ) ;
}
else if ( it - > first = = PROP_IMEI )
{
if ( m_simcard . empty ( ) )
{
__system_property_get ( " phone.imei " , value ) ;
it - > second = std : : string ( value ) ;
}
else
{
it - > second = m_simcard ;
}
}
else if ( it - > first = = PROP_OPERATION_TEMP )
{
it - > second = QueryCpuTemperature ( ) ;
}
else if ( it - > first = = PROP_FREE_ROM )
{
fs : : space_info si = fs : : space ( " /data " ) ;
it - > second = std : : to_string ( si . available ) ; // Unit: M
}
else if ( it - > first = = PROP_FREE_ROM_PERCENT )
{
fs : : space_info si = fs : : space ( " /data " ) ;
double fr = ( ( double ) si . available * 100.0f ) / ( ( double ) si . capacity ) ;
snprintf ( value , sizeof ( value ) , " %d%% " , ( int ) fr ) ;
it - > second = std : : string ( value ) ;
}
else if ( it - > first = = PROP_TOTAL_ROM )
{
fs : : space_info si = fs : : space ( " /data " ) ;
it - > second = std : : to_string ( si . capacity ) ; // Unit: M
}
else if ( it - > first = = PROP_FREE_MEMORY )
{
it - > second = std : : to_string ( android_os_Process_getFreeMemory ( ) ) ; // Unit: M
}
else if ( it - > first = = PROP_FREE_MEMORY_PERCENT )
{
long fm = android_os_Process_getFreeMemory ( ) ;
long tm = android_os_Process_getTotalMemory ( ) ;
double fmp = ( ( double ) fm * 100.0f ) / ( ( double ) tm ) ;
snprintf ( value , sizeof ( value ) , " %d%% " , ( int ) fmp ) ;
it - > second = std : : string ( value ) ; // Unit: M
}
else if ( it - > first = = PROP_TOTAL_MEMORY )
{
it - > second = std : : to_string ( android_os_Process_getTotalMemory ( ) ) ; // Unit: M
}
else if ( it - > first = = ( PROP_LIGHTDEPENDENT_RESISTOR ) )
{
int val = GpioControl : : getLightAdc ( ) ;
it - > second = std : : to_string ( val ) ;
}
else if ( it - > first = = ( PROP_CHARGING_CURRENT ) )
{
it - > second = std : : to_string ( GpioControl : : getChargingCurrent ( ) ) ;
}
else if ( it - > first = = ( PROP_CHARGING_POWER ) )
{
it - > second = std : : to_string ( GpioControl : : getChargingPower ( ) ) ;
}
else if ( it - > first = = ( PROP_CHARGING_BUS_VOL ) | | it - > first = = ( PROP_CHARGING_VOLTAGE ) )
{
double val = - 1 ;
char str [ 32 ] = { 0 } ;
for ( int idx = 0 ; idx < 3 ; idx + + )
{
val = GpioControl : : getChargingBusVoltage ( ) ;
if ( val < 0 )
{
continue ;
}
snprintf ( str , sizeof ( str ) , " %.1f " , ( val / 1000.0 ) ) ;
it - > second = std : : string ( str ) ;
break ;
}
}
else if ( it - > first = = ( PROP_BATTERY_POWER ) )
{
it - > second = std : : to_string ( GpioControl : : getBatteryPower ( ) ) ;
}
else if ( it - > first = = ( PROP_BATTERY_BUS_VOL ) | | it - > first = = ( PROP_BATTERY_VOLTAGE ) )
{
int val = QueryBatteryVoltage ( DEFAULT_BATTERY_QUERY_RETRIES ) ; // // BatVol
if ( val > 0 )
{
bv = val ;
snprintf ( value , sizeof ( value ) , " %.1f " , val / 1000.0 ) ;
it - > second = std : : string ( value ) ;
}
else
{
# ifdef _DEBUG
int aa = 0 ;
# endif
}
}
else if ( ( it - > first = = ( PROP_SIGNAL_4G ) ) | | ( it - > first = = ( PROP_SIGNAL_2G ) ) | | ( it - > first = = ( PROP_SIGNAL_LEVEL ) ) )
{
it - > second = std : : to_string ( m_signalLevel ) ;
}
/*
else if ( startsWith ( it - > first , PROP_JAVA_PREFIX ) )
{
if ( powerInfo . empty ( ) )
{
QueryPowerInfo ( powerInfo ) ;
}
auto it2 = powerInfo . find ( it - > first ) ;
if ( it2 ! = powerInfo . cend ( ) )
{
it - > second = it2 - > second ;
}
}
*/
}
std : : map < std : : string , std : : string > : : iterator it = properties . find ( PROP_BATTERY_CURRENT ) ;
if ( it ! = properties . end ( ) )
{
if ( bv = = - 1 )
{
bv = QueryBatteryVoltage ( DEFAULT_BATTERY_QUERY_RETRIES ) ;
}
if ( bv > 0 )
{
char str [ 32 ] = { 0 } ;
float batteryCurrent = STANDARD_CURRENT_64V / ( ( float ) bv / 1000.0f / STANDARD_VOLTAGE_64V ) ;
snprintf ( str , sizeof ( str ) , " %d " , ( int ) batteryCurrent ) ;
it - > second = std : : string ( str ) ;
}
}
// __system_property_get("ro.telephony.default_network", value);
return true ;
}
std : : string CPhoneDevice : : QueryCpuTemperature ( )
{
// /sys/devices/virtual/thermal/thermal_zone0/temp
std : : vector < unsigned char > data ;
// /sys/class/thermal/thermal zone*/temp
if ( readFile ( " /sys/class/thermal/thermal_zone3/temp " , data ) & & ! data . empty ( ) )
{
data . push_back ( 0 ) ;
int temp = atoi ( ( const char * ) ( & data [ 0 ] ) ) ;
return std : : to_string ( ( temp / 1000 ) + 20 ) ;
}
return " " ;
}
void CPhoneDevice : : QueryPowerInfo ( std : : map < std : : string , std : : string > & powerInfo )
{
JNIEnv * env = NULL ;
jboolean ret = JNI_FALSE ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
}
jobject jobj = env - > CallObjectMethod ( m_javaService , mGetSystemInfoMid ) ;
std : : string str = jstring2string ( env , ( jstring ) jobj ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
if ( ! str . empty ( ) )
{
std : : map < std : : string , std : : string > queries = parseQuery ( str ) ;
powerInfo . swap ( queries ) ;
}
}
bool CPhoneDevice : : GetNextScheduleItem ( uint32_t tsBasedZero , uint32_t scheduleTime , vector < uint32_t > & items )
{
return false ;
}
bool CPhoneDevice : : InstallAPP ( const std : : string & path , unsigned int delayedTime )
{
JNIEnv * env = NULL ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
}
jstring jpath = env - > NewStringUTF ( path . c_str ( ) ) ;
env - > CallBooleanMethod ( m_javaService , mInstallAppMid , jpath , ( jlong ) delayedTime ) ;
// env->ReleaseStringUTFChars(jpath, path.c_str());
env - > DeleteLocalRef ( jpath ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
return true ;
}
bool CPhoneDevice : : Reboot ( int resetType , bool manually , const std : : string & reason )
{
if ( resetType = = REBOOT_TYPE_DEVICE )
{
// reboot the device
if ( ! manually )
{
time_t rebootTime = GetRebootTime ( ) ;
time_t ts = time ( NULL ) ;
if ( ( ts - rebootTime ) < 1800 )
{
XYLOG ( XYLOG_SEVERITY_WARNING , " Frequent REBOOT DEV Cancelled Prev RBT Time=%lld " , ( int64_t ) rebootTime ) ;
return false ;
}
}
std : : thread t ( [ ] ( )
{
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1000 ) ) ;
GpioControl : : reboot ( ) ;
} ) ;
t . detach ( ) ;
}
else
{
long timeout = 1000 ;
RestartApp ( resetType , timeout , reason ) ;
}
return true ;
}
void CPhoneDevice : : RestartApp ( int resetType , long timeout , const std : : string & reason )
{
JNIEnv * env = NULL ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
}
jstring jreason = NULL ;
if ( ! reason . empty ( ) )
{
jreason = env - > NewStringUTF ( reason . c_str ( ) ) ;
}
env - > CallVoidMethod ( m_javaService , mRebootMid , resetType , timeout , jreason ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
}
bool CPhoneDevice : : EnableGPS ( bool enabled )
{
JNIEnv * env = NULL ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
return false ;
}
jboolean jenabled = enabled ? JNI_TRUE : JNI_FALSE ;
env - > CallVoidMethod ( m_javaService , mEnableGpsMid , jenabled ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
return true ;
}
float CPhoneDevice : : QueryBattaryVoltage ( int timesForAvg , bool * isCharging )
{
if ( timesForAvg < = 0 )
{
return 0.0f ;
}
int val = 0 ;
int totalVals = 0 ;
float chargingBusVoltage = 0.0f ;
for ( int idx = 0 ; idx < timesForAvg ; idx + + )
{
val = GpioControl : : getChargingBusVoltage ( ) ;
if ( val > 1000 )
{
chargingBusVoltage = ( float ) val / 1000.0 ;
break ;
}
}
if ( isCharging ! = NULL )
{
* isCharging = chargingBusVoltage > DEFAULT_WARNING_CHARGING_BUS_VOL ;
}
int matched = 0 ;
for ( int idx = 0 ; idx < timesForAvg ; idx + + )
{
val = GpioControl : : getBatteryVoltage ( ) ; // // BatVol
if ( val > 0 )
{
totalVals + = val > BATTARY_VOLTAGE_MAX ? BATTARY_VOLTAGE_MAX : val ;
matched + + ;
}
}
return ( matched > 0 ) ? ( ( float ) totalVals / 1000.0 / matched ) : 0 ;
}
bool CPhoneDevice : : RequestPosition ( )
{
JNIEnv * env = NULL ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
return false ;
}
jboolean ret = env - > CallBooleanMethod ( m_javaService , mRequestPositionMid ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
return ( ret = = JNI_TRUE ) ;
}
void CPhoneDevice : : handleSignal ( int sig , siginfo_t * si , void * uc )
{
TIMER_CONTEXT * context = ( TIMER_CONTEXT * ) ( si - > si_value . sival_ptr ) ;
context - > device - > handleTimerImpl ( context ) ;
}
bool CPhoneDevice : : RegisterHandlerForSignal ( int sig )
{
return true ;
// Establish handler for timer signal
struct sigaction sa ;
sigset_t mask ;
sa . sa_flags = SA_SIGINFO ;
sa . sa_sigaction = CPhoneDevice : : handleSignal ;
sigemptyset ( & sa . sa_mask ) ;
if ( sigaction ( sig , & sa , NULL ) = = - 1 )
{
return false ;
}
return true ;
// Block timer signal temporarily
// printf("Blocking signal %d\n", SIG);
sigemptyset ( & mask ) ;
sigaddset ( & mask , sig ) ;
if ( sigprocmask ( SIG_SETMASK , & mask , NULL ) = = - 1 )
{
return false ;
}
return true ;
}
void CPhoneDevice : : handleTimer ( union sigval v )
{
# ifdef _DEBUG
setThreadName ( " bztimer " ) ;
# endif
TIMER_CONTEXT * context = ( TIMER_CONTEXT * ) ( v . sival_ptr ) ;
context - > device - > handleTimerImpl ( context ) ;
}
void CPhoneDevice : : handleTimerImpl ( CPhoneDevice : : TIMER_CONTEXT * context )
{
context - > times + + ;
if ( context - > expectedTimes = = 0 | | context - > times < = context - > expectedTimes )
{
if ( m_listener ! = NULL )
{
m_listener - > OnTimeout ( context - > uid , context - > timerType , context - > data , context - > times ) ;
}
}
}
void CPhoneDevice : : handleRebootTimer ( union sigval v )
{
CPhoneDevice * pDevice = ( CPhoneDevice * ) ( v . sival_ptr ) ;
// Reboot APP
XYLOG ( XYLOG_SEVERITY_ERROR , " Camera Close Thread is DEAD, will RESTART app " ) ;
pDevice - > RestartApp ( 0 , 2000 , " Camera Can't Close " ) ;
}
// void CPhoneDevice::handleRebootTimerImpl()
// {
// }
IDevice : : timer_uid_t CPhoneDevice : : RegisterTimer ( unsigned int timerType , unsigned int timeout , void * data , unsigned long times /* = 0*/ )
{
struct sigevent evp = { 0 } ;
struct itimerspec ts = { 0 } ;
timer_t timer ;
int ret ;
TIMER_CONTEXT * context = new TIMER_CONTEXT ( ) ;
context - > device = this ;
context - > data = data ;
context - > timerType = timerType ;
context - > expectedTimes = times ;
context - > times = 0 ;
context - > uid = 0 ;
evp . sigev_value . sival_ptr = context ;
evp . sigev_notify = SIGEV_THREAD ; //SIGEV_THREAD_ID;
evp . sigev_notify_function = CPhoneDevice : : handleTimer ;
// evp.sigev_notify_thread_id = gettid();
// evp.sigev_notify = SIGEV_SIGNAL;
// evp.sigev_signo = SIGUSR2;
ret = timer_create ( CLOCK_REALTIME , & evp , & timer ) ;
if ( ret )
{
int err = errno ;
delete context ;
return INVALID_TIMER_UID ;
}
context - > uid = ( unsigned long ) timer ;
ts . it_value . tv_sec = ( timeout / 1000 ) ;
ts . it_value . tv_nsec = ( timeout % 1000 ) * 1000 ;
if ( times ! = 1 )
{
ts . it_interval . tv_sec = ts . it_value . tv_sec ;
ts . it_interval . tv_nsec = ts . it_value . tv_nsec ;
}
ret = timer_settime ( timer , 0 , & ts , NULL ) ;
if ( ret )
{
timer_delete ( timer ) ;
delete context ;
return INVALID_TIMER_UID ;
}
m_devLocker . lock ( ) ;
mTimers . insert ( mTimers . end ( ) , std : : pair < IDevice : : timer_uid_t , TIMER_CONTEXT * > ( ( IDevice : : timer_uid_t ) timer , context ) ) ;
m_devLocker . unlock ( ) ;
return ( IDevice : : timer_uid_t ) timer ;
}
bool CPhoneDevice : : UnregisterTimer ( IDevice : : timer_uid_t uid )
{
timer_t timer = ( timer_t ) uid ;
int res = timer_delete ( timer ) ;
m_devLocker . lock ( ) ;
std : : map < IDevice : : timer_uid_t , TIMER_CONTEXT * > : : iterator it = mTimers . find ( uid ) ;
if ( it ! = mTimers . end ( ) )
{
delete it - > second ;
mTimers . erase ( it ) ;
m_devLocker . unlock ( ) ;
return true ;
}
m_devLocker . unlock ( ) ;
return false ;
}
unsigned long CPhoneDevice : : RequestWakelock ( unsigned long timeout )
{
unsigned long wakelockId = m_wakelockIdFeed . fetch_add ( 1 ) ;
std : : string name = WAKELOCK_NAME ;
name + = to_string ( wakelockId ) ;
// ALOGI("RequestWakelock=%lld",wakelockId);
jboolean ret = JNI_FALSE ;
JNIEnv * env = NULL ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
return 0 ;
}
jstring jname = env - > NewStringUTF ( name . c_str ( ) ) ;
jlong jtimeout = ( jlong ) timeout ;
env - > CallVoidMethod ( m_javaService , mRequestWakelockMid , jname , jtimeout ) ;
// env->ReleaseStringUTFChars(jname, name.c_str());
env - > DeleteLocalRef ( jname ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
return wakelockId ;
}
bool CPhoneDevice : : ReleaseWakelock ( unsigned long wakelock )
{
// ALOGI("ReleaseWakelock=%lld", wakelock);
std : : string name = WAKELOCK_NAME ;
name + = to_string ( wakelock ) ;
jboolean ret = JNI_FALSE ;
JNIEnv * env = NULL ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
return false ;
}
jstring jname = env - > NewStringUTF ( name . c_str ( ) ) ;
env - > CallVoidMethod ( m_javaService , mReleaseWakelockMid , jname ) ;
env - > DeleteLocalRef ( jname ) ;
// env->ReleaseStringUTFChars(jname, name.c_str());
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
return true ;
}
IDevice : : timer_uid_t CPhoneDevice : : RegisterHeartbeat ( unsigned int timerType , unsigned int timeout , time_t tsForNextPhoto )
{
mHeartbeatStartTime = time ( NULL ) ;
mHeartbeatDuration = timeout ;
IDevice : : timer_uid_t uid = m_timerUidFeed . fetch_add ( 1 ) ;
jboolean ret = JNI_FALSE ;
JNIEnv * env = NULL ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
return 0 ;
}
# ifdef ALIGN_HB_TIMER_TO_PHOTO
env - > CallVoidMethod ( m_javaService , mRegisterHeartbeatMid , ( jint ) timeout , ( jlong ) tsForNextPhoto ) ;
# else
env - > CallVoidMethod ( m_javaService , mRegisterHeartbeatMid , ( jint ) timeout , 0 ) ;
# endif
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
return uid ;
}
bool CPhoneDevice : : TakePhoto ( const IDevice : : PHOTO_INFO & photoInfo , const vector < OSD_INFO > & osds , const std : : string & path )
{
if ( photoInfo . width = = 0 | | photoInfo . height = = 0 )
{
XYLOG ( XYLOG_SEVERITY_ERROR , " TP: Invalid Size: (%u-%u) PHOTOID=%u " , ( unsigned int ) photoInfo . width , ( unsigned int ) photoInfo . height , photoInfo . photoId ) ;
return false ;
}
if ( m_threadClose . joinable ( ) )
{
XYLOG ( XYLOG_SEVERITY_INFO , " TP: Wait Prev Thread CH=%u PR=%X PHOTOID=%u " , ( unsigned int ) photoInfo . channel , ( unsigned int ) photoInfo . preset , photoInfo . photoId ) ;
struct sigevent evp = { 0 } ;
struct itimerspec ts = { 0 } ;
timer_t timer ;
int ret ;
evp . sigev_value . sival_ptr = this ;
evp . sigev_notify = SIGEV_THREAD ; //SIGEV_THREAD_ID;
evp . sigev_notify_function = CPhoneDevice : : handleRebootTimer ;
// evp.sigev_notify_thread_id = gettid();
// evp.sigev_notify = SIGEV_SIGNAL;
// evp.sigev_signo = SIGUSR2;
ret = timer_create ( CLOCK_REALTIME , & evp , & timer ) ;
if ( ret = = 0 )
{
ts . it_value . tv_sec = 8 ; // 8 seconds
ts . it_value . tv_nsec = 0 ;
ret = timer_settime ( timer , 0 , & ts , NULL ) ;
}
m_threadClose . join ( ) ;
timer_delete ( timer ) ;
XYLOG ( XYLOG_SEVERITY_INFO , " TP: Wait Prev Thread End CH=%u PR=%X PHOTOID=%u " , ( unsigned int ) photoInfo . channel , ( unsigned int ) photoInfo . preset , photoInfo . photoId ) ;
}
if ( mCamera ! = NULL )
{
XYLOG ( XYLOG_SEVERITY_INFO , " TP: mCamera ISNOT null CH=%u PR=%X PHOTOID=%u " , ( unsigned int ) photoInfo . channel , ( unsigned int ) photoInfo . preset , photoInfo . photoId ) ;
delete mCamera ;
mCamera = NULL ;
}
XYLOG ( XYLOG_SEVERITY_INFO , " TP: CH=%u PR=%X PHOTOID=%u " , ( unsigned int ) photoInfo . channel , ( unsigned int ) photoInfo . preset , photoInfo . photoId ) ;
mPhotoInfo = photoInfo ;
mPath = path ;
mOsds = osds ;
bool res = false ;
if ( photoInfo . cameraType = = CAM_TYPE_USB | | photoInfo . cameraType = = CAM_TYPE_NET )
{
GpioControl : : setOtgState ( true ) ;
}
if ( photoInfo . cameraType = = CAM_TYPE_NET )
{
GpioControl : : set12VEnable ( true ) ;
# ifdef USING_N938
GpioControl : : TurnOn ( CMD_SET_NETWORK_POWER_EN ) ;
GpioControl : : TurnOn ( CMD_SET_485_EN_STATE ) ;
# else // USING_N938
# ifdef USING_PLZ
GpioControl : : TurnOn ( CMD_SET_100M_ENABLE ) ;
GpioControl : : TurnOn ( CMD_SET_100M_SWITCH_PWR_ENABLE ) ;
# endif // USING_PLZ
# endif // USING_N938
}
GpioControl : : setCam3V3Enable ( true ) ;
res = true ;
if ( ( mPhotoInfo . mediaType = = 0 ) & & ( ( mPhotoInfo . cameraType = = CAM_TYPE_MIPI ) | | ( mPhotoInfo . cameraType = = CAM_TYPE_USB ) ) )
{
NdkCamera : : CAMERA_PARAMS params ;
memset ( & params , 0 , sizeof ( params ) ) ;
params . sceneMode = mPhotoInfo . sceneMode ;
params . autoFocus = mPhotoInfo . autoFocus ;
params . autoExposure = mPhotoInfo . autoExposure ;
params . focusTimeout = mPhotoInfo . focusTimeout * 1000 ;
params . exposureTime = mPhotoInfo . exposureTime ;
params . sensitivity = mPhotoInfo . sensitivity ;
params . compensation = mPhotoInfo . compensation ;
params . orientation = mPhotoInfo . orientation ;
params . zoom = mPhotoInfo . zoom ;
params . zoomRatio = mPhotoInfo . zoomRatio ;
params . requestTemplate = mPhotoInfo . requestTemplate ;
params . awbMode = mPhotoInfo . awbMode ;
params . wait3ALocked = mPhotoInfo . wait3ALocked ;
params . burstRawCapture = mPhotoInfo . usingRawFormat ;
params . burstCaptures = mPhotoInfo . burstCaptures ;
if ( params . requestTemplate < = 0 | | params . requestTemplate > 5 )
{
params . requestTemplate = 2 ;
}
#if 0
if ( photoInfo . ldrEnabled )
{
if ( GpioControl : : getLightAdc ( ) > 1400 )
{
params . autoExposure = 0 ;
params . exposureTime = 1200000000 ;
params . sensitivity = 1200 ;
}
}
# endif
mCamera = new CPhoneCamera ( this , photoInfo . width , photoInfo . height , params ) ;
// mCamera = new CJpegCamera(this, photoInfo.width, photoInfo.height, mPath, params);
if ( mCamera - > open ( to_string ( mPhotoInfo . cameraId ) ) = = 0 )
{
XYLOG ( XYLOG_SEVERITY_DEBUG , " TP: Succeeded to OpenCamera CH=%u PR=%X PHOTOID=%u " , ( unsigned int ) photoInfo . channel , ( unsigned int ) photoInfo . preset , photoInfo . photoId ) ;
}
else
{
bool hasFatalError = mCamera - > HasFatalError ( ) ;
XYLOG ( XYLOG_SEVERITY_DEBUG , " TP: Failed to OpenCamera CH=%u PR=%X PHOTOID=%u " , ( unsigned int ) photoInfo . channel , ( unsigned int ) photoInfo . preset , photoInfo . photoId ) ;
delete mCamera ;
mCamera = NULL ;
res = false ;
GpioControl : : setCam3V3Enable ( false ) ;
if ( photoInfo . usbCamera )
{
GpioControl : : setOtgState ( false ) ;
}
if ( hasFatalError )
{
XYLOG ( XYLOG_SEVERITY_DEBUG , " TP: Fatal Error Happened, will RestartAPP in 60s CH=%u PR=%X PHOTOID=%u " , ( unsigned int ) photoInfo . channel , ( unsigned int ) photoInfo . preset , photoInfo . photoId ) ;
RestartApp ( REBOOT_TYPE_APP , 60000 , " FatalErrorOnCamera " ) ;
}
}
}
else if ( ( mPhotoInfo . mediaType = = 0 ) & & ( mPhotoInfo . cameraType = = CAM_TYPE_NET ) )
{
XYLOG ( XYLOG_SEVERITY_INFO , " Start TP on NET Camera CH=%u PR=%X PHOTOID=%u " , ( uint32_t ) mPhotoInfo . channel , ( uint32_t ) mPhotoInfo . preset , mPhotoInfo . photoId ) ;
// Start Thread
CPhoneDevice * pThis = this ;
vector < IDevice : : OSD_INFO > osds ;
osds . swap ( mOsds ) ;
IDevice : : PHOTO_INFO localPhotoInfo = mPhotoInfo ;
std : : thread t ( [ localPhotoInfo , path , pThis , osds ] ( ) mutable
{
// AutoEnv autoEnv(pThis->m_vm);
uint32_t waitTime = localPhotoInfo . selfTestingTime ;
waitTime = ( waitTime ! = 0 ) ? ( waitTime * 1024 ) : 10240 ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( waitTime ) ) ;
pThis - > SetStaticIp ( ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 256 ) ) ;
net_handle_t netHandle = pThis - > GetNetHandle ( ) ;
if ( netHandle = = 0 )
{
// Wait about 10s
for ( int idx = 0 ; idx < 84 ; idx + + )
{
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 128 ) ) ;
netHandle = pThis - > GetNetHandle ( ) ;
if ( netHandle ! = 0 )
{
break ;
}
}
}
if ( netHandle = = 0 )
{
// timeout
XYLOG ( XYLOG_SEVERITY_ERROR , " Ethernet not existing CH=%u PR=%X PHOTOID=%u " , ( uint32_t ) localPhotoInfo . channel , ( uint32_t ) localPhotoInfo . preset , localPhotoInfo . photoId ) ;
pThis - > TakePhotoCb ( 0 , localPhotoInfo , " " , 0 ) ;
GpioControl : : setOtgState ( false ) ;
GpioControl : : set12VEnable ( false ) ;
# ifdef USING_N938
GpioControl : : TurnOff ( CMD_SET_NETWORK_POWER_EN ) ;
GpioControl : : TurnOff ( CMD_SET_485_EN_STATE ) ;
# else // USING_N938
# ifdef USING_PLZ
GpioControl : : TurnOff ( CMD_SET_100M_ENABLE ) ;
GpioControl : : TurnOff ( CMD_SET_100M_SWITCH_PWR_ENABLE ) ;
# endif
# endif // USING_N938
return ;
}
else
{
XYLOG ( XYLOG_SEVERITY_INFO , " Ethernet is Available CH=%u PR=%X PHOTOID=%u " , ( uint32_t ) localPhotoInfo . channel , ( uint32_t ) localPhotoInfo . preset , localPhotoInfo . photoId ) ;
}
NET_PHOTO_INFO netPhotoInfo = { netHandle , 0 } ;
if ( localPhotoInfo . vendor = = 1 )
{
// Hai Kang
snprintf ( netPhotoInfo . url , sizeof ( netPhotoInfo . url ) , " /ISAPI/Streaming/channels/%u/picture " , ( uint32_t ) localPhotoInfo . channel ) ;
}
else if ( localPhotoInfo . vendor = = 2 )
{
// Hang Yu
strcpy ( netPhotoInfo . url , " /cgi-bin/snapshot.cgi " ) ;
}
else if ( localPhotoInfo . vendor = = 3 )
{
// Yu Shi
int streamSid = 0 ; // should put into config
snprintf ( netPhotoInfo . url , sizeof ( netPhotoInfo . url ) , " /LAPI/V1.0/Channels/%u/Media/Video/Streams/%d/Snapshot " , ( uint32_t ) localPhotoInfo . channel , streamSid ) ;
}
else
{
XYLOG ( XYLOG_SEVERITY_ERROR , " Vendor(%u) not Supported CH=%u PR=%X PHOTOID=%u " , ( uint32_t ) localPhotoInfo . vendor , ( uint32_t ) localPhotoInfo . channel , ( unsigned int ) localPhotoInfo . preset , localPhotoInfo . photoId ) ;
pThis - > TakePhotoCb ( 0 , localPhotoInfo , " " , 0 ) ;
GpioControl : : setOtgState ( false ) ;
GpioControl : : set12VEnable ( false ) ;
# ifdef USING_N938
GpioControl : : TurnOff ( CMD_SET_NETWORK_POWER_EN ) ;
GpioControl : : TurnOff ( CMD_SET_485_EN_STATE ) ;
# else // USING_N938
# ifdef USING_PLZ
GpioControl : : TurnOff ( CMD_SET_100M_ENABLE ) ;
GpioControl : : TurnOff ( CMD_SET_100M_SWITCH_PWR_ENABLE ) ;
# endif // USING_PLZ
# endif // USING_N938
return ;
}
struct in_addr addr ;
addr . s_addr = localPhotoInfo . ip ;
strcpy ( netPhotoInfo . ip , inet_ntoa ( addr ) ) ;
strcpy ( netPhotoInfo . outputPath , path . c_str ( ) ) ;
if ( ! localPhotoInfo . userName . empty ( ) )
{
size_t len = std : : min < size_t > ( sizeof ( netPhotoInfo . userName ) - 1 , localPhotoInfo . userName . size ( ) ) ;
strncpy ( netPhotoInfo . userName , localPhotoInfo . userName . c_str ( ) , len ) ;
}
if ( ! localPhotoInfo . password . empty ( ) )
{
size_t len = std : : min < size_t > ( sizeof ( netPhotoInfo . password ) - 1 , localPhotoInfo . password . size ( ) ) ;
strncpy ( netPhotoInfo . password , localPhotoInfo . password . c_str ( ) , len ) ;
}
// strcpy(netPhotoInfo.interface, "eth0");
std : : vector < uint8_t > img ;
bool netCaptureResult = false ;
for ( int idx = 0 ; idx < 3 ; idx + + )
{
netHandle = pThis - > GetNetHandle ( ) ;
netPhotoInfo . netHandle = netHandle ;
XYLOG ( XYLOG_SEVERITY_INFO , " NetCapture %d NetHandle=%lld PHOTOID=%u " , idx , netHandle , localPhotoInfo . photoId ) ;
netCaptureResult = requestCapture ( localPhotoInfo . channel , localPhotoInfo . preset , netPhotoInfo , img ) ;
if ( netCaptureResult )
{
break ;
}
}
GpioControl : : setOtgState ( false ) ;
GpioControl : : set12VEnable ( false ) ;
# ifdef USING_N938
GpioControl : : TurnOff ( CMD_SET_NETWORK_POWER_EN ) ;
GpioControl : : TurnOff ( CMD_SET_485_EN_STATE ) ;
# else // USING_N938
# ifdef USING_PLZ
GpioControl : : TurnOff ( CMD_SET_100M_ENABLE ) ;
GpioControl : : TurnOff ( CMD_SET_100M_SWITCH_PWR_ENABLE ) ;
# endif // USING_PLZ
# endif
if ( netCaptureResult )
{
time_t takingTime = time ( NULL ) ;
if ( localPhotoInfo . remedy ! = 0 )
{
if ( ( takingTime - localPhotoInfo . scheduleTime ) > 30 )
{
takingTime = localPhotoInfo . scheduleTime + localPhotoInfo . channel * 2 ;
}
}
localPhotoInfo . photoTime = takingTime ;
// Notify to take next photo
pThis - > TakePhotoCb ( 1 , localPhotoInfo , " " , takingTime ) ;
cv : : Mat rgb = cv : : imdecode ( cv : : Mat ( img ) , cv : : IMREAD_COLOR ) ;
# ifdef _DEBUG
// cv::imwrite("/sdcard/com.xypower.mpapp/tmp/netimg2.jpg", rgb);
# endif
netCaptureResult = pThis - > PostProcessPhoto ( localPhotoInfo , osds , path , " " , rgb ) ;
}
else
{
XYLOG ( XYLOG_SEVERITY_ERROR , " Faile to TP on NET Camera CH=%u PR=%X PHOTOID=%u URL=http://%s%s " , ( uint32_t ) localPhotoInfo . channel , ( uint32_t ) localPhotoInfo . preset ,
localPhotoInfo . photoId , netPhotoInfo . ip , netPhotoInfo . url ) ;
pThis - > TakePhotoCb ( 0 , localPhotoInfo , " " , 0 ) ;
}
} ) ;
t . detach ( ) ;
}
else if ( mPhotoInfo . mediaType = = 0 & & ( mPhotoInfo . cameraType = = CAM_TYPE_SERIAL ) )
{
CPhoneDevice * pThis = this ;
IDevice : : PHOTO_INFO localPhotoInfo = mPhotoInfo ;
IDevice : : SerialsPhotoParam param = { " " , 0 , 0 } ;
GetPhotoSerialsParamCb ( param ) ;
std : : thread t ( [ localPhotoInfo , param , pThis ] ( ) mutable
{
if ( localPhotoInfo . preset ! = 0 & & localPhotoInfo . preset ! = 0xFF )
{
CameraPhotoCmd ( time ( NULL ) , localPhotoInfo . channel , MOVE_PRESETNO , 0 , localPhotoInfo . preset , param . serfile , param . baud , param . addr ) ;
std : : this_thread : : sleep_for ( std : : chrono : : seconds ( 3 ) ) ;
}
time_t ts = time ( NULL ) ;
if ( ! pThis - > GetPTZSensorsStatus ( ) & & ! pThis - > GetCameraStatus ( ) )
{
XYLOG ( XYLOG_SEVERITY_INFO , " Camera is SeltTesting, selfTestingtime=%u " , ( uint32_t ) localPhotoInfo . selfTestingTime ) ;
pThis - > OpenPTZSensors ( localPhotoInfo . selfTestingTime ) ;
}
CameraPhotoCmd ( ts , localPhotoInfo . channel , 0 , localPhotoInfo . resolution , 0 , param . serfile , param . baud , param . addr ) ;
XYLOG ( XYLOG_SEVERITY_INFO , " Taking photo over " ) ;
pThis - > TakePTZPhotoCb ( 3 , localPhotoInfo ) ;
} ) ;
t . detach ( ) ;
}
else if ( mPhotoInfo . usingSysCamera = = 1 )
{
JNIEnv * env = NULL ;
bool didAttachThread = false ;
res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
return false ;
}
IDevice : : PHOTO_INFO * pPhotoInfo = new IDevice : : PHOTO_INFO ( mPhotoInfo ) ;
jboolean photoOrVideo = mPhotoInfo . mediaType = = 0 ? JNI_TRUE : JNI_FALSE ;
env - > CallVoidMethod ( m_javaService , mCallSysCameraMid , mPhotoInfo . cameraId ,
reinterpret_cast < jlong > ( pPhotoInfo ) ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
}
else
{
JNIEnv * env = NULL ;
bool didAttachThread = false ;
res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
return false ;
}
jstring leftTopOSD = NULL ;
jstring rightTopOSD = NULL ;
jstring rightBottomOSD = NULL ;
jstring leftBottomOSD = NULL ;
for ( vector < OSD_INFO > : : const_iterator it = mOsds . cbegin ( ) ; it ! = mOsds . cend ( ) ; + + it )
{
if ( it - > text . empty ( ) )
{
continue ;
}
switch ( it - > alignment )
{
case OSD_ALIGNMENT_TOP_LEFT :
leftTopOSD = env - > NewStringUTF ( it - > text . c_str ( ) ) ;
break ;
case OSD_ALIGNMENT_TOP_RIGHT :
rightTopOSD = env - > NewStringUTF ( it - > text . c_str ( ) ) ;
break ;
case OSD_ALIGNMENT_BOTTOM_RIGHT :
rightBottomOSD = env - > NewStringUTF ( it - > text . c_str ( ) ) ;
break ;
case OSD_ALIGNMENT_BOTTOM_LEFT :
leftBottomOSD = env - > NewStringUTF ( it - > text . c_str ( ) ) ;
break ;
}
}
int orientation = mPhotoInfo . orientation = = 0 ? - 1 : ( mPhotoInfo . orientation - 1 ) * 90 ;
jboolean photoOrVideo = mPhotoInfo . mediaType = = 0 ? JNI_TRUE : JNI_FALSE ;
env - > CallVoidMethod ( m_javaService , mStartRecordingMid , photoOrVideo , mPhotoInfo . cameraId , ( unsigned long ) mPhotoInfo . photoId ,
mPhotoInfo . duration , mPhotoInfo . width , mPhotoInfo . height , mPhotoInfo . duration , orientation ,
leftTopOSD , rightTopOSD , rightBottomOSD , leftBottomOSD ) ;
if ( leftTopOSD ) env - > DeleteLocalRef ( leftTopOSD ) ;
if ( rightTopOSD ) env - > DeleteLocalRef ( rightTopOSD ) ;
if ( rightBottomOSD ) env - > DeleteLocalRef ( rightBottomOSD ) ;
if ( leftBottomOSD ) env - > DeleteLocalRef ( leftBottomOSD ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
}
return res ;
}
bool CPhoneDevice : : OpenPTZSensors ( int sec )
{
{
std : : lock_guard < std : : mutex > lock ( m_cameraLocker ) ;
// std::unique_lock<std::mutex> lock(m_cameraLocker);
if ( ! m_cameraStatus & & ! m_sensorsStatus )
{
m_sensorsStatus = true ;
OpenSensors ( MAIN_POWER_OPEN ) ;
OpenSensors ( CAMERA_SENSOR_OPEN ) ;
}
}
if ( m_sensorsStatus & & ! m_cameraStatus )
{
auto start = std : : chrono : : steady_clock : : now ( ) ;
while ( std : : chrono : : steady_clock : : now ( ) - start < std : : chrono : : seconds ( sec ) )
{
if ( m_shouldStopWaiting . load ( ) )
{
CloseSensors ( CAMERA_SENSOR_OPEN ) ;
CloseSensors ( MAIN_POWER_OPEN ) ;
m_cameraStatus = false ;
m_sensorsStatus = false ;
m_shouldStopWaiting . store ( false ) ;
return false ;
}
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 200 ) ) ;
}
}
// if(m_sensorsStatus && !m_cameraStatus)
// std::this_thread::sleep_for(std::chrono::seconds(sec));
{
std : : lock_guard < std : : mutex > lock ( m_cameraLocker ) ;
// std::unique_lock<std::mutex> lock(m_cameraLocker);
if ( ! m_cameraStatus & & m_sensorsStatus )
{
m_cameraStatus = true ;
}
}
return m_cameraStatus ;
}
bool CPhoneDevice : : ClosePTZSensors ( )
{
if ( m_sensorsStatus & & ! m_cameraStatus )
{
m_shouldStopWaiting . store ( true ) ;
}
else if ( m_sensorsStatus & & m_cameraStatus )
{
std : : lock_guard < std : : mutex > lock ( m_cameraLocker ) ;
// std::unique_lock<std::mutex> lock(m_cameraLocker);
CloseSensors ( CAMERA_SENSOR_OPEN ) ;
CloseSensors ( MAIN_POWER_OPEN ) ;
m_cameraStatus = false ;
m_sensorsStatus = false ;
}
return true ;
}
bool CPhoneDevice : : GetPTZSensorsStatus ( )
{
std : : lock_guard < std : : mutex > lock ( m_cameraLocker ) ;
return m_sensorsStatus ;
}
bool CPhoneDevice : : GetCameraStatus ( )
{
std : : lock_guard < std : : mutex > lock ( m_cameraLocker ) ;
return m_cameraStatus ;
}
bool CPhoneDevice : : CloseCamera ( )
{
if ( mCamera ! = NULL )
{
auto camera = mCamera ;
mCamera = NULL ;
camera - > close ( ) ;
delete camera ;
}
return true ;
}
void CPhoneDevice : : CloseCamera2 ( CPhoneDevice : : CPhoneCamera * camera , unsigned int photoId , unsigned char cameraType )
{
XYLOG ( XYLOG_SEVERITY_DEBUG , " TP: Start CloseCamera PHOTOID=%u " , photoId ) ;
// std::this_thread::sleep_for(std::chrono::milliseconds(16));
if ( camera ! = NULL )
{
camera - > close ( ) ;
delete camera ;
}
XYLOG ( XYLOG_SEVERITY_DEBUG , " TP: Will Turn Off Power PHOTOID=%u " , photoId ) ;
if ( cameraType = = CAM_TYPE_NET )
{
GpioControl : : set12VEnable ( false ) ;
}
if ( cameraType = = CAM_TYPE_USB | | cameraType = = CAM_TYPE_NET )
{
GpioControl : : setOtgState ( false ) ;
}
GpioControl : : setCam3V3Enable ( false ) ;
XYLOG ( XYLOG_SEVERITY_DEBUG , " TP: End Turn Off Power PHOTOID=%u " , photoId ) ;
XYLOG ( XYLOG_SEVERITY_DEBUG , " TP: CloseCamera PHOTOID=%u " , photoId ) ;
}
void visualize ( const char * filename , const ncnn : : Mat & m )
{
cv : : Mat a ( m . h , m . w , CV_8UC3 ) ;
m . to_pixels ( a . data , ncnn : : Mat : : PIXEL_BGR2RGB ) ;
cv : : imwrite ( filename , a ) ;
}
void DrawOutlineText ( cv : : Ptr < cv : : ft : : FreeType2 > ft2 , cv : : Mat & mat , const std : : string & str , cv : : Point startPoint , int fontSize , cv : : Scalar clr , int thickness )
{
std : : vector < std : : string > lines = split ( str , " \n " ) ;
int lineHeight = 0 ;
cv : : Point pt = startPoint ;
cv : : Size textSize ;
int baseline = 0 ;
for ( std : : vector < std : : string > : : const_iterator it = lines . cbegin ( ) ; it ! = lines . cend ( ) ; + + it )
{
textSize = ft2 - > getTextSize ( * it , fontSize , thickness , & baseline ) ;
lineHeight = std : : max ( fontSize , textSize . height + baseline ) ;
ft2 - > putText ( mat , * it , pt , fontSize , clr , thickness , cv : : LINE_AA , false , true ) ;
pt . x = startPoint . x ;
pt . y + = lineHeight + ( lineHeight > > 2 ) ; // 125%
}
}
bool CPhoneDevice : : onOneCapture ( std : : shared_ptr < ACameraMetadata > characteristics ,
std : : shared_ptr < ACameraMetadata > result ,
uint32_t ldr , uint32_t duration , cv : : Mat rgb )
{
time_t takingTime = time ( NULL ) ;
if ( mPhotoInfo . remedy ! = 0 )
{
if ( ( takingTime - mPhotoInfo . scheduleTime ) > 30 )
{
takingTime = mPhotoInfo . scheduleTime + mPhotoInfo . channel * 2 ;
}
}
mPhotoInfo . photoTime = takingTime ;
vector < IDevice : : OSD_INFO > osds ;
osds . swap ( mOsds ) ;
PHOTO_INFO photoInfo = mPhotoInfo ;
std : : string path ;
path . swap ( mPath ) ;
// std::string tmpPath = m_appPath + std::string(APP_DIR_TMP DIR_SEP_STR) + std::to_string(photoInfo.photoId);
acamera_metadata_enum_android_lens_facing_t facing = ACAMERA_LENS_FACING_FRONT ;
ACameraMetadata_const_entry e = { 0 } ;
camera_status_t status = ACameraMetadata_getConstEntry ( characteristics . get ( ) , ACAMERA_LENS_FACING , & e ) ;
if ( status = = ACAMERA_OK )
{
facing = ( acamera_metadata_enum_android_lens_facing_t ) e . data . u8 [ 0 ] ;
}
int sensorOrientation = 0 ;
{
ACameraMetadata_const_entry e = { 0 } ;
status = ACameraMetadata_getConstEntry ( characteristics . get ( ) , ACAMERA_SENSOR_ORIENTATION , & e ) ;
if ( status = = ACAMERA_OK )
{
sensorOrientation = ( int ) e . data . i32 [ 0 ] ;
}
}
bool turnOffOtg = ( photoInfo . usbCamera ! = 0 ) ;
CPhoneCamera * pCamera = mCamera ;
mCamera = NULL ;
media_status_t mstatus ;
std : : thread closeThread ( & CPhoneDevice : : CloseCamera2 , this , pCamera , photoInfo . photoId , photoInfo . cameraType ) ;
m_threadClose . swap ( closeThread ) ;
if ( closeThread . joinable ( ) )
{
closeThread . detach ( ) ;
}
CPhoneDevice * pThis = this ;
std : : thread th ( [ pThis , characteristics , result , photoInfo , osds , path , rgb , facing , sensorOrientation , ldr , duration , takingTime ] ( ) mutable
{
std : : string cameraInfo ;
if ( photoInfo . outputDbgInfo ! = 0 )
{
NdkCamera : : CAPTURE_RESULT captureResult = { 0 } ;
NdkCamera : : EnumCameraResult ( result . get ( ) , captureResult ) ;
char extimeunit [ 4 ] = { 0 } ;
unsigned int extime = ( captureResult . exposureTime > = 1000000 ) ? ( ( unsigned int ) ( captureResult . exposureTime / 1000000 ) ) : ( ( unsigned int ) ( captureResult . exposureTime / 1000 ) ) ;
strcpy ( extimeunit , ( captureResult . exposureTime > = 1000000 ) ? " ms " : " μs " ) ;
char str [ 128 ] = { 0 } ;
snprintf ( str , sizeof ( str ) , " AE=%u AF=%u EXPS=%u%s(%d) ISO=%d AFS=%u AES=%u AWBS=%u SCENE=%d LDR=%d(%u) %0.1fx T=%u FD=%lld " ,
captureResult . autoExposure , captureResult . autoFocus ,
extime , extimeunit , captureResult . compensation , captureResult . sensitivity ,
// isnan(captureResult.FocusDistance) ? 0 : captureResult.FocusDistance,
( unsigned int ) captureResult . afState , ( unsigned int ) captureResult . aeState , captureResult . awbState ,
captureResult . sceneMode , GpioControl : : getLightAdc ( ) , ldr , captureResult . zoomRatio ,
duration , captureResult . frameDuration ) ;
cameraInfo = str ;
}
# ifdef OUTPUT_CAMERA_DBG_INFO
#if 0
bool shouldRetry = false ;
if ( ldr ! = ~ 0 )
{
if ( ldr < MIN_LIGHT_Y )
{
if ( photoInfo . retries < ( DEFAULT_TAKE_PHOTO_RETRIES - 1 ) )
{
shouldRetry = true ;
char presetBuf [ 16 ] = { 0 } ;
snprintf ( presetBuf , sizeof ( presetBuf ) , " %02X " , photoInfo . retries ) ;
// replaceAll(fullPath, ".jpg", std::string("-") + std::to_string(photoInfo.retries) + ".jpg");
replaceAll ( fullPath , " _FF_ " , std : : string ( " _ " ) + presetBuf + std : : string ( " _ " ) ) ;
XYLOG ( XYLOG_SEVERITY_ERROR , " Photo is TOO dark or light(LDR=%u), will RETRY it " ,
( uint32_t ) captureResult . avgY ) ;
// photoInfo.usingRawFormat = 1;
}
}
else if ( ldr > MAX_LIGHT_Y )
{
if ( photoInfo . retries < ( DEFAULT_TAKE_PHOTO_RETRIES - 1 ) )
{
shouldRetry = true ;
char presetBuf [ 16 ] = { 0 } ;
snprintf ( presetBuf , sizeof ( presetBuf ) , " %02X " , photoInfo . retries ) ;
// replaceAll(fullPath, ".jpg", std::string("-") + std::to_string(photoInfo.retries) + ".jpg");
replaceAll ( fullPath , " _FF_ " , std : : string ( " _ " ) + presetBuf + std : : string ( " _ " ) ) ;
XYLOG ( XYLOG_SEVERITY_ERROR , " Photo is TOO dark or light(LDR=%u), will RETRY it " ,
( uint32_t ) captureResult . avgY ) ;
}
photoInfo . compensation = - 2 * ( ( int16_t ) ( ( uint16_t ) captureResult . avgY ) ) ;
}
}
# endif // 0
# endif // OUTPUT_CAMERA_DBG_INFO
// Notify to take next photo
pThis - > TakePhotoCb ( 1 , photoInfo , " " , takingTime ) ;
bool res = pThis - > PostProcessPhoto ( photoInfo , osds , path , cameraInfo , rgb ) ;
if ( res )
{
// TakePhotoCb(2, photoInfo, path, takingTime);
}
} ) ;
th . detach ( ) ;
return true ;
}
bool CPhoneDevice : : onBurstCapture ( std : : shared_ptr < ACameraMetadata > characteristics ,
std : : vector < std : : shared_ptr < ACameraMetadata > > & results ,
uint32_t ldr , uint32_t duration , std : : vector < std : : vector < uint8_t > > & frames )
{
time_t takingTime = time ( NULL ) ;
if ( mPhotoInfo . remedy ! = 0 )
{
if ( ( takingTime - mPhotoInfo . scheduleTime ) > 30 )
{
takingTime = mPhotoInfo . scheduleTime + mPhotoInfo . channel * 2 ;
}
}
mPhotoInfo . photoTime = takingTime ;
vector < IDevice : : OSD_INFO > osds ;
osds . swap ( mOsds ) ;
PHOTO_INFO photoInfo = mPhotoInfo ;
std : : string path ;
path . swap ( mPath ) ;
// std::string tmpPath = m_appPath + std::string(APP_DIR_TMP DIR_SEP_STR) + std::to_string(photoInfo.photoId);
std : : shared_ptr < ByteArraysPointer > pByteArrays = std : : make_shared < ByteArraysPointer > ( ) ;
pByteArrays . get ( ) - > byteArrays . swap ( frames ) ;
bool turnOffOtg = ( photoInfo . usbCamera ! = 0 ) ;
CPhoneCamera * pCamera = mCamera ;
mCamera = NULL ;
std : : thread closeThread ( & CPhoneDevice : : CloseCamera2 , this , pCamera , photoInfo . photoId , photoInfo . cameraType ) ;
m_threadClose . swap ( closeThread ) ;
if ( closeThread . joinable ( ) )
{
closeThread . detach ( ) ;
}
CPhoneDevice * pThis = this ;
std : : thread th ( [ pThis , characteristics , results , photoInfo , osds , path , pByteArrays , ldr , duration , takingTime ] ( ) mutable
{
cv : : Mat rgb ;
std : : string cameraInfo ;
media_status_t mstatus ;
acamera_metadata_enum_android_lens_facing_t facing = ACAMERA_LENS_FACING_FRONT ;
ACameraMetadata_const_entry e = { 0 } ;
camera_status_t status = ACameraMetadata_getConstEntry ( characteristics . get ( ) , ACAMERA_LENS_FACING , & e ) ;
if ( status = = ACAMERA_OK )
{
facing = ( acamera_metadata_enum_android_lens_facing_t ) e . data . u8 [ 0 ] ;
}
int sensorOrientation = 0 ;
{
ACameraMetadata_const_entry e = { 0 } ;
status = ACameraMetadata_getConstEntry ( characteristics . get ( ) , ACAMERA_SENSOR_ORIENTATION , & e ) ;
if ( status = = ACAMERA_OK )
{
sensorOrientation = ( int ) e . data . i32 [ 0 ] ;
}
}
if ( photoInfo . outputDbgInfo ! = 0 )
{
if ( ! results . empty ( ) )
{
NdkCamera : : CAPTURE_RESULT captureResult = { 0 } ;
NdkCamera : : EnumCameraResult ( results [ 0 ] . get ( ) , captureResult ) ;
char extimeunit [ 4 ] = { 0 } ;
unsigned int extime = ( captureResult . exposureTime > = 1000000 ) ? ( ( unsigned int ) ( captureResult . exposureTime / 1000000 ) ) : ( ( unsigned int ) ( captureResult . exposureTime / 1000 ) ) ;
strcpy ( extimeunit , ( captureResult . exposureTime > = 1000000 ) ? " ms " : " μs " ) ;
char str [ 128 ] = { 0 } ;
snprintf ( str , sizeof ( str ) , " AE=%u AF=%u EXPS=%u%s(%d) ISO=%d AFS=%u AES=%u AWBS=%u SCENE=%d LDR=%d(%u) %0.1fx T=%u FD=%lld BURST " ,
captureResult . autoExposure , captureResult . autoFocus ,
extime , extimeunit , captureResult . compensation , captureResult . sensitivity ,
// isnan(captureResult.FocusDistance) ? 0 : captureResult.FocusDistance,
( unsigned int ) captureResult . afState , ( unsigned int ) captureResult . aeState , captureResult . awbState ,
captureResult . sceneMode , GpioControl : : getLightAdc ( ) , ldr , captureResult . zoomRatio ,
duration , captureResult . frameDuration ) ;
cameraInfo = str ;
}
}
# ifdef OUTPUT_CAMERA_DBG_INFO
#if 0
bool shouldRetry = false ;
if ( ldr ! = ~ 0 )
{
if ( ldr < MIN_LIGHT_Y )
{
if ( photoInfo . retries < ( DEFAULT_TAKE_PHOTO_RETRIES - 1 ) )
{
shouldRetry = true ;
char presetBuf [ 16 ] = { 0 } ;
snprintf ( presetBuf , sizeof ( presetBuf ) , " %02X " , photoInfo . retries ) ;
// replaceAll(fullPath, ".jpg", std::string("-") + std::to_string(photoInfo.retries) + ".jpg");
replaceAll ( fullPath , " _FF_ " , std : : string ( " _ " ) + presetBuf + std : : string ( " _ " ) ) ;
XYLOG ( XYLOG_SEVERITY_ERROR , " Photo is TOO dark or light(LDR=%u), will RETRY it " ,
( uint32_t ) captureResult . avgY ) ;
// photoInfo.usingRawFormat = 1;
}
}
else if ( ldr > MAX_LIGHT_Y )
{
if ( photoInfo . retries < ( DEFAULT_TAKE_PHOTO_RETRIES - 1 ) )
{
shouldRetry = true ;
char presetBuf [ 16 ] = { 0 } ;
snprintf ( presetBuf , sizeof ( presetBuf ) , " %02X " , photoInfo . retries ) ;
// replaceAll(fullPath, ".jpg", std::string("-") + std::to_string(photoInfo.retries) + ".jpg");
replaceAll ( fullPath , " _FF_ " , std : : string ( " _ " ) + presetBuf + std : : string ( " _ " ) ) ;
XYLOG ( XYLOG_SEVERITY_ERROR , " Photo is TOO dark or light(LDR=%u), will RETRY it " ,
( uint32_t ) captureResult . avgY ) ;
}
photoInfo . compensation = - 2 * ( ( int16_t ) ( ( uint16_t ) captureResult . avgY ) ) ;
}
}
# endif // 0
# endif // OUTPUT_CAMERA_DBG_INFO
// Notify to take next photo
pThis - > TakePhotoCb ( 1 , photoInfo , " " , takingTime ) ;
# ifdef USING_EXEC_HDRP
if ( photoInfo . usingNewHdrplus )
{
XYLOG ( XYLOG_SEVERITY_ERROR , " Start HDR CH=%u IMGID=%u " , ( uint32_t ) photoInfo . channel , ( uint32_t ) photoInfo . photoId ) ;
std : : vector < std : : vector < uint8_t > > localFrames ;
localFrames . swap ( pByteArrays . get ( ) - > byteArrays ) ;
# ifdef _DEBUG
std : : vector < uint8_t > & firstFrame = localFrames [ 0 ] ;
writeFile ( " /sdcard/com.xypower.mpapp/tmp/dngs/1.dng " , & firstFrame [ 0 ] , firstFrame . size ( ) ) ;
writeFile ( " /sdcard/com.xypower.mpapp/tmp/dngs/2.dng " , & localFrames [ 1 ] [ 0 ] , localFrames [ 1 ] . size ( ) ) ;
writeFile ( " /sdcard/com.xypower.mpapp/tmp/dngs/3.dng " , & localFrames [ 2 ] [ 0 ] , localFrames [ 2 ] . size ( ) ) ;
writeFile ( " /sdcard/com.xypower.mpapp/tmp/dngs/4.dng " , & localFrames [ 3 ] [ 0 ] , localFrames [ 3 ] . size ( ) ) ;
// readFile("/sdcard/com.xypower.mpapp/tmp/dngs/001.dng", localFrames[0]);
// readFile("/sdcard/com.xypower.mpapp/tmp/dngs/002.dng", localFrames[1]);
// readFile("/sdcard/com.xypower.mpapp/tmp/dngs/003.dng", localFrames[2]);
// readFile("/sdcard/com.xypower.mpapp/tmp/dngs/004.dng", localFrames[3]);
# endif
doHdrPlus ( localFrames , rgb ) ;
cv : : cvtColor ( rgb . clone ( ) , rgb , cv : : COLOR_RGB2BGR ) ;
localFrames . clear ( ) ;
# ifdef _DEBUG
std : : vector < int > params ;
params . push_back ( cv : : IMWRITE_JPEG_QUALITY ) ;
params . push_back ( 95 ) ;
cv : : imwrite ( " /sdcard/com.xypower.mpapp/tmp/1.jpg " , rgb , params ) ;
# endif
XYLOG ( XYLOG_SEVERITY_ERROR , " Finish HDR CH=%u IMGID=%u " , ( uint32_t ) photoInfo . channel , ( uint32_t ) photoInfo . photoId ) ;
{
cv : : Mat tempPic = convert16bit2_8bit_ ( rgb ) ;
rgb = tempPic ;
}
if ( photoInfo . orientation > 0 )
{
if ( photoInfo . orientation = = 1 )
{
if ( facing = = ACAMERA_LENS_FACING_FRONT )
{
cv : : flip ( rgb , rgb , 1 ) ;
}
}
else if ( photoInfo . orientation = = 2 )
{
cv : : Mat tempPic ;
cv : : transpose ( rgb , tempPic ) ;
cv : : flip ( tempPic , rgb , 1 ) ;
}
else if ( photoInfo . orientation = = 3 )
{
if ( facing = = ACAMERA_LENS_FACING_FRONT )
{
flip ( rgb , rgb , 0 ) ;
}
else
{
cv : : flip ( rgb , rgb , - 1 ) ;
}
}
else if ( ( photoInfo . orientation % 4 ) = = 0 )
{
cv : : Mat tempPic ;
cv : : transpose ( rgb , tempPic ) ;
cv : : flip ( tempPic , rgb , 0 ) ;
}
XYLOG ( XYLOG_SEVERITY_ERROR , " Finish rotation CH=%u IMGID=%u " , ( uint32_t ) photoInfo . channel , ( uint32_t ) photoInfo . photoId ) ;
}
// cv::cvtColor(rgb, rgb, cv::COLOR_RGB2BGR);
}
else
{
uint64_t uniqueId = pThis - > m_uniqueIdFeed . fetch_add ( 1 ) ;
std : : string tmpDir = pThis - > m_appPath + ( APP_DIR_TMP DIR_SEP_STR ) + std : : to_string ( uniqueId ) + DIR_SEP_STR ;
EnsureDirectoryPathExists ( tmpDir ) ;
std : : vector < std : : vector < uint8_t > > localFrames ;
localFrames . swap ( pByteArrays . get ( ) - > byteArrays ) ;
std : : string outputPath = tmpDir + " output.bmp " ;
size_t numberOfFrames = localFrames . size ( ) ;
std : : vector < std : : string > imagePaths ;
for ( int idx = 0 ; idx < localFrames . size ( ) ; idx + + )
{
std : : string imagePath = tmpDir + std : : to_string ( idx ) + " .dng " ;
std : : vector < uint8_t > & frame = localFrames [ idx ] ;
if ( writeFile ( imagePath , & frame [ 0 ] , frame . size ( ) ) )
{
imagePaths . push_back ( imagePath ) ;
}
}
localFrames . clear ( ) ;
int exitCode = pThis - > CallExecv ( photoInfo . orientation , facing = = ACAMERA_LENS_FACING_FRONT ? 1 : 0 , outputPath , imagePaths ) ;
for ( auto it = imagePaths . cbegin ( ) ; it ! = imagePaths . cend ( ) ; + + it )
{
std : : remove ( ( * it ) . c_str ( ) ) ;
}
if ( existsFile ( outputPath ) )
{
rgb = cv : : imread ( outputPath ) ;
std : : remove ( outputPath . c_str ( ) ) ;
}
std : : error_code errCode ;
fs : : remove_all ( fs : : path ( tmpDir ) , errCode ) ;
}
# else // USING_EXEC_HDRP
XYLOG ( XYLOG_SEVERITY_ERROR , " Start HDR CH=%u IMGID=%u " , ( uint32_t ) photoInfo . channel , ( uint32_t ) photoInfo . photoId ) ;
hdrplus : : hdrplus_pipeline pipeline ;
std : : vector < std : : vector < uint8_t > > localFrames ;
localFrames . swap ( pByteArrays . get ( ) - > byteArrays ) ;
pipeline . run_pipeline ( localFrames , 0 , rgb ) ;
localFrames . clear ( ) ;
XYLOG ( XYLOG_SEVERITY_ERROR , " Finish HDR CH=%u IMGID=%u " , ( uint32_t ) photoInfo . channel , ( uint32_t ) photoInfo . photoId ) ;
{
cv : : Mat tempPic = convert16bit2_8bit_ ( rgb ) ;
rgb = tempPic ;
}
if ( photoInfo . orientation > 0 )
{
if ( photoInfo . orientation = = 1 )
{
if ( facing = = ACAMERA_LENS_FACING_FRONT )
{
cv : : flip ( rgb , rgb , 1 ) ;
}
}
else if ( photoInfo . orientation = = 2 )
{
cv : : Mat tempPic ;
cv : : transpose ( rgb , tempPic ) ;
cv : : flip ( tempPic , rgb , 1 ) ;
}
else if ( photoInfo . orientation = = 3 )
{
if ( facing = = ACAMERA_LENS_FACING_FRONT )
{
flip ( rgb , rgb , 0 ) ;
}
else
{
cv : : flip ( rgb , rgb , - 1 ) ;
}
}
else if ( ( photoInfo . orientation % 4 ) = = 0 )
{
cv : : Mat tempPic ;
cv : : transpose ( rgb , tempPic ) ;
cv : : flip ( tempPic , rgb , 0 ) ;
}
XYLOG ( XYLOG_SEVERITY_ERROR , " Finish rotation CH=%u IMGID=%u " , ( uint32_t ) photoInfo . channel , ( uint32_t ) photoInfo . photoId ) ;
}
cv : : cvtColor ( rgb , rgb , cv : : COLOR_RGB2BGR ) ;
# endif // USING_EXEC_HDRP
bool res = pThis - > PostProcessPhoto ( photoInfo , osds , path , cameraInfo , rgb ) ;
if ( res )
{
// TakePhotoCb(2, photoInfo, path, takingTime);
}
} ) ;
th . detach ( ) ;
return true ;
}
bool CPhoneDevice : : onBurstCapture ( std : : shared_ptr < ACameraMetadata > characteristics ,
std : : vector < std : : shared_ptr < ACameraMetadata > > & results ,
uint32_t ldr , uint32_t duration , std : : vector < std : : shared_ptr < AImage > > & frames )
{
time_t takingTime = time ( NULL ) ;
if ( mPhotoInfo . remedy ! = 0 )
{
if ( ( takingTime - mPhotoInfo . scheduleTime ) > 30 )
{
takingTime = mPhotoInfo . scheduleTime + mPhotoInfo . channel * 2 ;
}
}
mPhotoInfo . photoTime = takingTime ;
vector < IDevice : : OSD_INFO > osds ;
osds . swap ( mOsds ) ;
PHOTO_INFO photoInfo = mPhotoInfo ;
std : : string path ;
path . swap ( mPath ) ;
// std::string tmpPath = m_appPath + std::string(APP_DIR_TMP DIR_SEP_STR) + std::to_string(photoInfo.photoId);
acamera_metadata_enum_android_lens_facing_t facing = ACAMERA_LENS_FACING_FRONT ;
ACameraMetadata_const_entry e = { 0 } ;
camera_status_t status = ACameraMetadata_getConstEntry ( characteristics . get ( ) , ACAMERA_LENS_FACING , & e ) ;
if ( status = = ACAMERA_OK )
{
facing = ( acamera_metadata_enum_android_lens_facing_t ) e . data . u8 [ 0 ] ;
}
int sensorOrientation = 0 ;
{
ACameraMetadata_const_entry e = { 0 } ;
status = ACameraMetadata_getConstEntry ( characteristics . get ( ) , ACAMERA_SENSOR_ORIENTATION , & e ) ;
if ( status = = ACAMERA_OK )
{
sensorOrientation = ( int ) e . data . i32 [ 0 ] ;
}
}
bool turnOffOtg = ( photoInfo . usbCamera ! = 0 ) ;
CPhoneCamera * pCamera = mCamera ;
mCamera = NULL ;
cv : : Mat rgb ;
media_status_t mstatus ;
std : : vector < std : : shared_ptr < hdrplus : : MemFile > > rawFiles ;
if ( photoInfo . usingRawFormat ! = 0 )
{
for ( int idx = 0 ; idx < frames . size ( ) ; idx + + )
{
std : : shared_ptr < AImage > spImage = frames [ idx ] ;
std : : shared_ptr < ACameraMetadata > spResult = results [ idx ] ;
hdrplus : : MemFile * rawImage = new hdrplus : : MemFile ( ) ;
rawFiles . push_back ( std : : shared_ptr < hdrplus : : MemFile > ( rawImage ) ) ;
// rawImage->FromAImage(spImage.get(), characteristics.get(), spResult.get());
int32_t width = 0 ;
int32_t height = 0 ;
mstatus = AImage_getWidth ( spImage . get ( ) , & width ) ;
mstatus = AImage_getHeight ( spImage . get ( ) , & height ) ;
int32_t planeCount = 0 ;
mstatus = AImage_getNumberOfPlanes ( spImage . get ( ) , & planeCount ) ;
AASSERT ( mstatus = = AMEDIA_OK & & planeCount = = 1 , " Error: getNumberOfPlanes() planeCount = %d " , planeCount ) ;
uint8_t * planeData = NULL ;
int planeDataLen = 0 ;
mstatus = AImage_getPlaneData ( spImage . get ( ) , 0 , & planeData , & planeDataLen ) ;
ALOGD ( " Start Converting Dng " ) ;
DngCreator dngCreator ( characteristics . get ( ) , spResult . get ( ) ) ;
dngCreator . writeInputBuffer ( rawImage - > content , planeData , planeDataLen , width , height , 0 ) ;
ALOGD ( " End Converting Dng " ) ;
}
}
else
{
if ( results . size ( ) = = 1 & & frames . size ( ) = = 1 )
{
std : : shared_ptr < ACameraMetadata > result = results [ 0 ] ;
std : : shared_ptr < AImage > frame = frames [ 0 ] ;
int32_t format ;
mstatus = AImage_getFormat ( frame . get ( ) , & format ) ;
if ( format = = AIMAGE_FORMAT_YUV_420_888 )
{
int32_t width ;
int32_t height ;
mstatus = AImage_getWidth ( frame . get ( ) , & width ) ;
mstatus = AImage_getHeight ( frame . get ( ) , & height ) ;
int32_t y_pixelStride = 0 ;
int32_t u_pixelStride = 0 ;
int32_t v_pixelStride = 0 ;
AImage_getPlanePixelStride ( frame . get ( ) , 0 , & y_pixelStride ) ;
AImage_getPlanePixelStride ( frame . get ( ) , 1 , & u_pixelStride ) ;
AImage_getPlanePixelStride ( frame . get ( ) , 2 , & v_pixelStride ) ;
int32_t y_rowStride = 0 ;
int32_t u_rowStride = 0 ;
int32_t v_rowStride = 0 ;
AImage_getPlaneRowStride ( frame . get ( ) , 0 , & y_rowStride ) ;
AImage_getPlaneRowStride ( frame . get ( ) , 1 , & u_rowStride ) ;
AImage_getPlaneRowStride ( frame . get ( ) , 2 , & v_rowStride ) ;
uint8_t * y_data = 0 ;
uint8_t * u_data = 0 ;
uint8_t * v_data = 0 ;
int y_len = 0 ;
int u_len = 0 ;
int v_len = 0 ;
AImage_getPlaneData ( frame . get ( ) , 0 , & y_data , & y_len ) ;
AImage_getPlaneData ( frame . get ( ) , 1 , & u_data , & u_len ) ;
AImage_getPlaneData ( frame . get ( ) , 2 , & v_data , & v_len ) ;
if ( u_data = = v_data + 1 & & v_data = = y_data + width * height & & y_pixelStride = = 1 & & u_pixelStride = = 2 & & v_pixelStride = = 2 & & y_rowStride = = width & & u_rowStride = = width & & v_rowStride = = width )
{
// already nv21
ConvertYUV21ToMat ( y_data , width , height , photoInfo . width , photoInfo . height , sensorOrientation , facing = = ACAMERA_LENS_FACING_FRONT , photoInfo . orientation , rgb ) ;
}
else
{
// construct nv21
uint8_t * nv21 = new uint8_t [ width * height + width * height / 2 ] ;
{
// Y
uint8_t * yptr = nv21 ;
for ( int y = 0 ; y < height ; y + + )
{
const uint8_t * y_data_ptr = y_data + y_rowStride * y ;
for ( int x = 0 ; x < width ; x + + )
{
yptr [ 0 ] = y_data_ptr [ 0 ] ;
yptr + + ;
y_data_ptr + = y_pixelStride ;
}
}
// UV
uint8_t * uvptr = nv21 + width * height ;
for ( int y = 0 ; y < height / 2 ; y + + )
{
const uint8_t * v_data_ptr = v_data + v_rowStride * y ;
const uint8_t * u_data_ptr = u_data + u_rowStride * y ;
for ( int x = 0 ; x < width / 2 ; x + + )
{
uvptr [ 0 ] = v_data_ptr [ 0 ] ;
uvptr [ 1 ] = u_data_ptr [ 0 ] ;
uvptr + = 2 ;
v_data_ptr + = v_pixelStride ;
u_data_ptr + = u_pixelStride ;
}
}
}
ConvertYUV21ToMat ( nv21 , width , height , photoInfo . width , photoInfo . height , sensorOrientation , facing = = ACAMERA_LENS_FACING_FRONT , photoInfo . orientation , rgb ) ;
delete [ ] nv21 ;
}
}
}
}
frames . clear ( ) ;
std : : thread closeThread ( & CPhoneDevice : : CloseCamera2 , this , pCamera , photoInfo . photoId , mPhotoInfo . cameraType ) ;
m_threadClose . swap ( closeThread ) ;
if ( closeThread . joinable ( ) )
{
closeThread . detach ( ) ;
}
CPhoneDevice * pThis = this ;
std : : thread th ( [ pThis , characteristics , results , photoInfo , osds , path , rgb , rawFiles , facing , sensorOrientation , ldr , duration , takingTime ] ( ) mutable
{
std : : string cameraInfo ;
if ( photoInfo . outputDbgInfo ! = 0 )
{
if ( ! results . empty ( ) )
{
NdkCamera : : CAPTURE_RESULT captureResult = { 0 } ;
NdkCamera : : EnumCameraResult ( results [ 0 ] . get ( ) , captureResult ) ;
char extimeunit [ 4 ] = { 0 } ;
unsigned int extime = ( captureResult . exposureTime > = 1000000 ) ? ( ( unsigned int ) ( captureResult . exposureTime / 1000000 ) ) : ( ( unsigned int ) ( captureResult . exposureTime / 1000 ) ) ;
strcpy ( extimeunit , ( captureResult . exposureTime > = 1000000 ) ? " ms " : " μs " ) ;
char str [ 128 ] = { 0 } ;
snprintf ( str , sizeof ( str ) , " AE=%u AF=%u EXPS=%u%s(%d) ISO=%d AFS=%u AES=%u AWBS=%u SCENE=%d LDR=%d(%u) %0.1fx T=%u FD=%lld " ,
captureResult . autoExposure , captureResult . autoFocus ,
extime , extimeunit , captureResult . compensation , captureResult . sensitivity ,
// isnan(captureResult.FocusDistance) ? 0 : captureResult.FocusDistance,
( unsigned int ) captureResult . afState , ( unsigned int ) captureResult . aeState , captureResult . awbState ,
captureResult . sceneMode , GpioControl : : getLightAdc ( ) , ldr , captureResult . zoomRatio ,
duration , captureResult . frameDuration ) ;
cameraInfo = str ;
}
}
# ifdef OUTPUT_CAMERA_DBG_INFO
#if 0
bool shouldRetry = false ;
if ( ldr ! = ~ 0 )
{
if ( ldr < MIN_LIGHT_Y )
{
if ( photoInfo . retries < ( DEFAULT_TAKE_PHOTO_RETRIES - 1 ) )
{
shouldRetry = true ;
char presetBuf [ 16 ] = { 0 } ;
snprintf ( presetBuf , sizeof ( presetBuf ) , " %02X " , photoInfo . retries ) ;
// replaceAll(fullPath, ".jpg", std::string("-") + std::to_string(photoInfo.retries) + ".jpg");
replaceAll ( fullPath , " _FF_ " , std : : string ( " _ " ) + presetBuf + std : : string ( " _ " ) ) ;
XYLOG ( XYLOG_SEVERITY_ERROR , " Photo is TOO dark or light(LDR=%u), will RETRY it " ,
( uint32_t ) captureResult . avgY ) ;
// photoInfo.usingRawFormat = 1;
}
}
else if ( ldr > MAX_LIGHT_Y )
{
if ( photoInfo . retries < ( DEFAULT_TAKE_PHOTO_RETRIES - 1 ) )
{
shouldRetry = true ;
char presetBuf [ 16 ] = { 0 } ;
snprintf ( presetBuf , sizeof ( presetBuf ) , " %02X " , photoInfo . retries ) ;
// replaceAll(fullPath, ".jpg", std::string("-") + std::to_string(photoInfo.retries) + ".jpg");
replaceAll ( fullPath , " _FF_ " , std : : string ( " _ " ) + presetBuf + std : : string ( " _ " ) ) ;
XYLOG ( XYLOG_SEVERITY_ERROR , " Photo is TOO dark or light(LDR=%u), will RETRY it " ,
( uint32_t ) captureResult . avgY ) ;
}
photoInfo . compensation = - 2 * ( ( int16_t ) ( ( uint16_t ) captureResult . avgY ) ) ;
}
}
# endif // 0
# endif // OUTPUT_CAMERA_DBG_INFO
// Notify to take next photo
pThis - > TakePhotoCb ( 1 , photoInfo , " " , takingTime ) ;
if ( photoInfo . usingRawFormat ! = 0 )
{
# ifndef USING_EXEC_HDRP
XYLOG ( XYLOG_SEVERITY_ERROR , " Start HDR CH=%u IMGID=%u " , ( uint32_t ) photoInfo . channel , ( uint32_t ) photoInfo . photoId ) ;
hdrplus : : hdrplus_pipeline pipeline ;
pipeline . run_pipeline ( rawFiles , 0 , rgb ) ;
rawFiles . clear ( ) ;
# endif
XYLOG ( XYLOG_SEVERITY_ERROR , " Finish HDR CH=%u IMGID=%u " , ( uint32_t ) photoInfo . channel , ( uint32_t ) photoInfo . photoId ) ;
{
cv : : Mat tempPic = convert16bit2_8bit_ ( rgb ) ;
rgb = tempPic ;
}
if ( photoInfo . orientation > 0 )
{
if ( photoInfo . orientation = = 1 )
{
if ( facing = = ACAMERA_LENS_FACING_FRONT )
{
cv : : flip ( rgb , rgb , 1 ) ;
}
} else if ( photoInfo . orientation = = 2 )
{
cv : : Mat tempPic ;
cv : : transpose ( rgb , tempPic ) ;
cv : : flip ( tempPic , rgb , 1 ) ;
}
else if ( photoInfo . orientation = = 3 )
{
if ( facing = = ACAMERA_LENS_FACING_FRONT )
{
flip ( rgb , rgb , 0 ) ;
}
else
{
cv : : flip ( rgb , rgb , - 1 ) ;
}
}
else if ( photoInfo . orientation = = 4 )
{
cv : : Mat tempPic ;
cv : : transpose ( rgb , tempPic ) ;
cv : : flip ( tempPic , rgb , 0 ) ;
}
XYLOG ( XYLOG_SEVERITY_ERROR , " Finish rotation CH=%u IMGID=%u " , ( uint32_t ) photoInfo . channel , ( uint32_t ) photoInfo . photoId ) ;
}
cv : : cvtColor ( rgb , rgb , cv : : COLOR_RGB2BGR ) ;
}
bool res = pThis - > PostProcessPhoto ( photoInfo , osds , path , cameraInfo , rgb ) ;
if ( res )
{
// TakePhotoCb(2, photoInfo, path, takingTime);
}
} ) ;
th . detach ( ) ;
return true ;
}
int CPhoneDevice : : CallExecv ( int rotation , int frontCamera , const std : : string & outputPath , const std : : vector < std : : string > & images )
{
JNIEnv * env = NULL ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
}
std : : string pathsWithSpace ;
for ( auto it = images . cbegin ( ) ; it ! = images . cend ( ) ; + + it )
{
pathsWithSpace . append ( * it ) ;
pathsWithSpace . append ( " " ) ;
}
pathsWithSpace . pop_back ( ) ;
jstring joutputPath = env - > NewStringUTF ( outputPath . c_str ( ) ) ;
jstring jpathWithSpace = env - > NewStringUTF ( pathsWithSpace . c_str ( ) ) ;
jint exitCode = env - > CallIntMethod ( m_javaService , mExecHdrplusMid , rotation , frontCamera , joutputPath , jpathWithSpace ) ;
env - > DeleteLocalRef ( jpathWithSpace ) ;
env - > DeleteLocalRef ( joutputPath ) ;
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
return exitCode ;
}
bool CPhoneDevice : : OnImageReady ( cv : : Mat & mat )
{
time_t takingTime = time ( NULL ) ;
if ( mPhotoInfo . remedy ! = 0 )
{
if ( ( takingTime - mPhotoInfo . scheduleTime ) > 30 )
{
takingTime = mPhotoInfo . scheduleTime + mPhotoInfo . channel * 2 ;
}
}
mPhotoInfo . photoTime = takingTime ;
int baseline = 0 ;
cv : : Size textSize ;
double height = mat . size ( ) . height ;
double width = mat . size ( ) . width ;
// double ratio = std::min(height / 1024, width / 1920);
double ratio = height / 1024.0 ;
int thickness = round ( 1.4 * ratio ) ;
if ( thickness < 1 ) thickness = 1 ;
else if ( thickness > 5 ) thickness = 5 ;
cv : : Scalar scalarWhite ( 255 , 255 , 255 ) ; // white
int fontSize = ( int ) ( 28.0 * ratio ) ;
cv : : Point pt ;
std : : string fontPath ;
if ( existsFile ( " /system/fonts/NotoSansCJK-Regular.ttc " ) )
{
fontPath = " /system/fonts/NotoSansCJK-Regular.ttc " ;
}
else if ( existsFile ( " /system/fonts/NotoSerifCJK-Regular.ttc " ) )
{
fontPath = " /system/fonts/NotoSerifCJK-Regular.ttc " ;
}
else
{
fontPath = m_appPath + " fonts/Noto.otf " ;
}
cv : : Ptr < cv : : ft : : FreeType2 > ft2 ;
ft2 = cv : : ft : : createFreeType2 ( ) ;
ft2 - > loadFontData ( fontPath . c_str ( ) , 0 ) ;
// cv::Rect rc(0, 0, mat.cols, mat.rows);
// cv::rectangle (mat, rc, cv::Scalar(255, 255, 255), cv::FILLED);
std : : vector < IDevice : : RECOG_OBJECT > objs ;
if ( ( m_pRecognizationCfg ! = NULL ) & & ( m_pRecognizationCfg - > enabled ! = 0 ) & & ( mPhotoInfo . recognization ! = 0 ) )
{
XYLOG ( XYLOG_SEVERITY_INFO , " Channel AI Enabled " ) ;
// visualize(ncnnPath.c_str(), in);
# ifdef _DEBUG
double startTime = ncnn : : get_current_time ( ) ;
# endif // _DEBUG
bool detected = YoloV5NcnnDetect ( mat , true , m_pRecognizationCfg - > blobName8 , m_pRecognizationCfg - > blobName16 , m_pRecognizationCfg - > blobName32 , objs ) ;
# ifdef _DEBUG
double elasped = ncnn : : get_current_time ( ) - startTime ;
// __android_log_print(ANDROID_LOG_DEBUG, "YoloV5Ncnn", "%.2fms detect", elasped);
# endif // _DEBUG
# ifdef _DEBUG
ALOGI ( " NCNN recognization: %.2fms res=%d " , elasped , ( ( detected & & ! objs . empty ( ) ) ? 1 : 0 ) ) ;
# endif
if ( detected & & ! objs . empty ( ) )
{
#if 0
static const char * class_names [ ] = {
" person " , " bicycle " , " car " , " motorcycle " , " airplane " , " bus " , " train " , " truck " , " boat " , " traffic light " ,
" fire hydrant " , " stop sign " , " parking meter " , " bench " , " bird " , " cat " , " dog " , " horse " , " sheep " , " cow " ,
" elephant " , " bear " , " zebra " , " giraffe " , " backpack " , " umbrella " , " handbag " , " tie " , " suitcase " , " frisbee " ,
" skis " , " snowboard " , " sports ball " , " kite " , " baseball bat " , " baseball glove " , " skateboard " , " surfboard " ,
" tennis racket " , " bottle " , " wine glass " , " cup " , " fork " , " knife " , " spoon " , " bowl " , " banana " , " apple " ,
" sandwich " , " orange " , " broccoli " , " carrot " , " hot dog " , " pizza " , " donut " , " cake " , " chair " , " couch " ,
" potted plant " , " bed " , " dining table " , " toilet " , " tv " , " laptop " , " mouse " , " remote " , " keyboard " , " cell phone " ,
" microwave " , " oven " , " toaster " , " sink " , " refrigerator " , " book " , " clock " , " vase " , " scissors " , " teddy bear " ,
" hair drier " , " toothbrush "
} ;
# endif
cv : : Scalar borderColor ( m_pRecognizationCfg - > borderColor & 0xFF , ( m_pRecognizationCfg - > borderColor & 0xFF00 ) > > 8 , ( m_pRecognizationCfg - > borderColor & 0xFF0000 ) > > 16 ) ;
cv : : Scalar textColor ( m_pRecognizationCfg - > textColor & 0xFF , ( m_pRecognizationCfg - > textColor & 0xFF00 ) > > 8 , ( m_pRecognizationCfg - > textColor & 0xFF0000 ) > > 16 ) ;
float minSizeW = m_pRecognizationCfg - > minSize > 0 ? ( mPhotoInfo . width * m_pRecognizationCfg - > minSize / 100 ) : 0 ;
float minSizeH = m_pRecognizationCfg - > minSize > 0 ? ( mPhotoInfo . height * m_pRecognizationCfg - > minSize / 100 ) : 0 ;
for ( std : : vector < IDevice : : RECOG_OBJECT > : : const_iterator it = objs . cbegin ( ) ; it ! = objs . cend ( ) ; )
{
if ( it - > label > = m_pRecognizationCfg - > items . size ( ) )
{
it = objs . erase ( it ) ;
continue ;
}
const IDevice : : CFG_RECOGNIZATION : : ITEM & item = m_pRecognizationCfg - > items [ it - > label ] ;
if ( item . enabled = = 0 | | it - > prob < item . prob )
{
it = objs . erase ( it ) ;
continue ;
}
if ( m_pRecognizationCfg - > minSize > 0 )
{
if ( it - > w < minSizeW | | it - > h < minSizeH )
{
it = objs . erase ( it ) ;
continue ;
}
}
if ( ( mPhotoInfo . recognization & 0x2 ) ! = 0 )
{
cv : : Rect rc ( it - > x , it - > y , it - > w , it - > h ) ;
cv : : rectangle ( mat , rc , borderColor , m_pRecognizationCfg - > thickness ) ;
textSize = ft2 - > getTextSize ( item . name , fontSize , thickness , & baseline ) ;
textSize . height + = baseline ;
if ( it - > y > textSize . height )
{
pt . y = it - > y - textSize . height - 4 - m_pRecognizationCfg - > thickness ;
}
else if ( mat . rows - it - > y - it - > h > textSize . height )
{
pt . y = it - > y + it - > h + 4 + m_pRecognizationCfg - > thickness ;
}
else
{
// Inner
pt . y = it - > y + 4 + m_pRecognizationCfg - > thickness ;
}
if ( mat . cols - it - > x > textSize . width )
{
pt . x = it - > x ;
}
else
{
pt . x = it - > x + it - > w - textSize . width ;
}
# ifdef OUTPUT_CAMERA_DBG_INFO
char buf [ 128 ] ;
snprintf ( buf , sizeof ( buf ) , " AI: %d=%s (%f,%f)-(%f,%f) Text:(%d,%d)-(%d,%d) " ,
it - > label , item . name . c_str ( ) , it - > x , it - > y , it - > w , it - > h , pt . x , pt . y , textSize . width , textSize . height ) ;
XYLOG ( XYLOG_SEVERITY_DEBUG , buf ) ;
# endif
ft2 - > putText ( mat , item . name + std : : to_string ( ( int ) ( it - > prob * 100.0 ) ) + " % " , pt , fontSize , textColor , thickness , cv : : LINE_AA , false , true ) ;
}
+ + it ;
}
}
}
else
{
XYLOG ( XYLOG_SEVERITY_WARNING , " Channel AI Disabled " ) ;
}
// #ifdef OUTPUT_CAMERA_DBG_INFO
if ( mCamera ! = NULL )
{
if ( mPhotoInfo . outputDbgInfo ! = 0 )
{
cv : : Scalar scalarRed ( 0 , 0 , 255 ) ; // red
char extimeunit [ 4 ] = { 0 } ;
char str [ 128 ] = { 0 } ;
int fs = fontSize * 2 / 3 ;
textSize = ft2 - > getTextSize ( str , fs , - 1 , & baseline ) ;
cv : : Point lt ( 0 , mat . rows - fs - 20 * ratio ) ;
cv : : Point lt2 ( 0 , lt . y - 2 * ratio ) ;
cv : : Point rb ( 0 + textSize . width + 2 * ratio , lt2 . y + textSize . height + 8 * ratio ) ;
if ( rb . x > ( int ) width - 1 )
{
rb . x = ( int ) width - 1 ;
}
if ( rb . y > ( int ) height - 1 )
{
rb . y = ( int ) height - 1 ;
}
cv : : Mat roi = mat ( cv : : Rect ( lt2 , rb ) ) ;
cv : : Mat clrMat ( roi . size ( ) , CV_8UC3 , scalarWhite ) ;
double alpha = 0.5 ;
cv : : addWeighted ( clrMat , alpha , roi , 1.0 - alpha , 0.0 , roi ) ;
// cv::rectangle(mat, lt2, rb,cv::Scalar(255, 255, 255), -1);
ft2 - > putText ( mat , str , lt , fs , scalarRed , - 1 , cv : : LINE_AA , false ) ;
// DrawOutlineText(ft2, mat, str, cv::Point(0, mat.rows - fs - 20 * ratio), fs, scalarWhite, 1);
}
}
// #endif // OUTPUT_CAMERA_DBG_INFO
for ( vector < OSD_INFO > : : const_iterator it = mOsds . cbegin ( ) ; it ! = mOsds . cend ( ) ; + + it )
{
if ( it - > text . empty ( ) )
{
continue ;
}
# ifdef _DEBUG
if ( it - > alignment = = OSD_ALIGNMENT_BOTTOM_RIGHT )
{
int aa = 0 ;
}
# endif
textSize = ft2 - > getTextSize ( it - > text , fontSize , thickness , & baseline ) ;
XYLOG ( XYLOG_SEVERITY_DEBUG , " %s font Size=%d height: %d baseline=%d " , it - > text . c_str ( ) , fontSize , textSize . height , baseline ) ;
if ( it - > alignment = = OSD_ALIGNMENT_TOP_LEFT )
{
pt . x = it - > x * ratio ;
pt . y = it - > y * ratio ;
}
else if ( it - > alignment = = OSD_ALIGNMENT_TOP_RIGHT )
{
pt . x = width - textSize . width - it - > x * ratio ;
pt . y = it - > y * ratio ;
}
else if ( it - > alignment = = OSD_ALIGNMENT_BOTTOM_RIGHT )
{
pt . x = width - textSize . width - it - > x * ratio ;
pt . y = height - it - > y * ratio - textSize . height - baseline ;
}
else if ( it - > alignment = = OSD_ALIGNMENT_BOTTOM_LEFT )
{
pt . x = it - > x * ratio ;
pt . y = height - it - > y * ratio - textSize . height - baseline ;
}
// cv::Rect rc(pt.x, pt.y, textSize.width, textSize.height);
// cv::rectangle(mat, rc, cv::Scalar(0,255,255), 2);
DrawOutlineText ( ft2 , mat , it - > text , pt , fontSize , scalarWhite , thickness ) ;
}
std : : vector < int > params ;
params . push_back ( cv : : IMWRITE_JPEG_QUALITY ) ;
params . push_back ( ( int ) ( ( uint32_t ) mPhotoInfo . quality ) ) ;
bool res = false ;
std : : string fullPath = endsWith ( mPath , " .jpg " ) ? mPath : ( mPath + CTerminal : : BuildPhotoFileName ( mPhotoInfo ) ) ;
# ifdef OUTPUT_CAMERA_DBG_INFO
bool shouldRetry = false ;
#if 0
if ( mCamera ! = NULL ) {
NdkCamera : : CAPTURE_RESULT captureResult = mCamera - > getCaptureResult ( ) ;
if ( captureResult . avgY < MIN_LIGHT_Y )
{
if ( mPhotoInfo . retries < ( DEFAULT_TAKE_PHOTO_RETRIES - 1 ) )
{
shouldRetry = true ;
char presetBuf [ 16 ] = { 0 } ;
snprintf ( presetBuf , sizeof ( presetBuf ) , " %02X " , mPhotoInfo . retries ) ;
// replaceAll(fullPath, ".jpg", std::string("-") + std::to_string(mPhotoInfo.retries) + ".jpg");
replaceAll ( fullPath , " _FF_ " , std : : string ( " _ " ) + presetBuf + std : : string ( " _ " ) ) ;
XYLOG ( XYLOG_SEVERITY_ERROR , " Photo is TOO dark or light(LDR=%u), will RETRY it " ,
( uint32_t ) captureResult . avgY ) ;
// mPhotoInfo.usingRawFormat = 1;
}
}
else if ( captureResult . avgY > MAX_LIGHT_Y )
{
if ( mPhotoInfo . retries < ( DEFAULT_TAKE_PHOTO_RETRIES - 1 ) )
{
shouldRetry = true ;
char presetBuf [ 16 ] = { 0 } ;
snprintf ( presetBuf , sizeof ( presetBuf ) , " %02X " , mPhotoInfo . retries ) ;
// replaceAll(fullPath, ".jpg", std::string("-") + std::to_string(mPhotoInfo.retries) + ".jpg");
replaceAll ( fullPath , " _FF_ " , std : : string ( " _ " ) + presetBuf + std : : string ( " _ " ) ) ;
XYLOG ( XYLOG_SEVERITY_ERROR , " Photo is TOO dark or light(LDR=%u), will RETRY it " ,
( uint32_t ) captureResult . avgY ) ;
}
mPhotoInfo . compensation = - 2 * ( ( int16_t ) ( ( uint16_t ) captureResult . avgY ) ) ;
}
}
# endif
# endif // OUTPUT_CAMERA_DBG_INFO
if ( ! std : : filesystem : : exists ( std : : filesystem : : path ( fullPath ) ) )
{
bool res = cv : : imwrite ( fullPath . c_str ( ) , mat , params ) ;
if ( ! res )
{
XYLOG ( XYLOG_SEVERITY_ERROR , " Failed to write photo: %s " , fullPath . c_str ( ) ) ;
}
else
{
XYLOG ( XYLOG_SEVERITY_INFO , " Succeeded to write photo: %s " , fullPath . c_str ( ) ) ;
}
# ifdef OUTPUT_CAMERA_DBG_INFO
if ( shouldRetry )
{
TakePhotoCb ( 0 , mPhotoInfo , fullPath , takingTime , objs ) ;
}
else
{
TakePhotoCb ( res ? 3 : 0 , mPhotoInfo , fullPath , takingTime , objs ) ;
}
# else
TakePhotoCb ( res ? 3 : 0 , mPhotoInfo , fullPath , takingTime , objs ) ;
# endif
}
else
{
ALOGI ( " Photo file exists: %s " , mPath . c_str ( ) ) ;
}
return res ;
}
bool CPhoneDevice : : PostProcessPhoto ( const PHOTO_INFO & photoInfo , const vector < IDevice : : OSD_INFO > & osds , const std : : string & path , const std : : string & cameraInfo , cv : : Mat & mat )
{
int baseline = 0 ;
cv : : Size textSize ;
double height = mat . rows ;
double width = mat . cols ;
// double ratio = std::min(height / 1024, width / 1920);
double ratio = height / 1024.0 ;
int thickness = round ( 1.4 * ratio ) ;
if ( thickness < 1 ) thickness = 1 ;
else if ( thickness > 5 ) thickness = 5 ;
cv : : Scalar scalarWhite ( 255 , 255 , 255 ) ; // white
int fontSize = ( int ) ( 28.0 * ratio ) ;
cv : : Point pt ;
std : : string fontPath ;
if ( existsFile ( " /system/fonts/NotoSansCJK-Regular.ttc " ) )
{
fontPath = " /system/fonts/NotoSansCJK-Regular.ttc " ;
}
else if ( existsFile ( " /system/fonts/NotoSerifCJK-Regular.ttc " ) )
{
fontPath = " /system/fonts/NotoSerifCJK-Regular.ttc " ;
}
else
{
fontPath = m_appPath + " fonts/Noto.otf " ;
}
cv : : Ptr < cv : : ft : : FreeType2 > ft2 ;
ft2 = cv : : ft : : createFreeType2 ( ) ;
ft2 - > loadFontData ( fontPath . c_str ( ) , 0 ) ;
// cv::Rect rc(0, 0, mat.cols, mat.rows);
// cv::rectangle (mat, rc, cv::Scalar(255, 255, 255), cv::FILLED);
std : : vector < IDevice : : RECOG_OBJECT > objs ;
if ( ( m_pRecognizationCfg ! = NULL ) & & ( m_pRecognizationCfg - > enabled ! = 0 ) & & ( photoInfo . recognization ! = 0 ) )
{
XYLOG ( XYLOG_SEVERITY_INFO , " Channel AI Enabled " ) ;
// visualize(ncnnPath.c_str(), in);
# ifdef _DEBUG
double startTime = ncnn : : get_current_time ( ) ;
# endif // _DEBUG
bool detected = YoloV5NcnnDetect ( mat , true , m_pRecognizationCfg - > blobName8 , m_pRecognizationCfg - > blobName16 , m_pRecognizationCfg - > blobName32 , objs ) ;
# ifdef _DEBUG
double elasped = ncnn : : get_current_time ( ) - startTime ;
// __android_log_print(ANDROID_LOG_DEBUG, "YoloV5Ncnn", "%.2fms detect", elasped);
# endif // _DEBUG
# ifdef _DEBUG
ALOGI ( " NCNN recognization: %.2fms res=%d " , elasped , ( ( detected & & ! objs . empty ( ) ) ? 1 : 0 ) ) ;
# endif
if ( detected & & ! objs . empty ( ) )
{
cv : : Scalar borderColor ( m_pRecognizationCfg - > borderColor & 0xFF , ( m_pRecognizationCfg - > borderColor & 0xFF00 ) > > 8 , ( m_pRecognizationCfg - > borderColor & 0xFF0000 ) > > 16 ) ;
cv : : Scalar textColor ( m_pRecognizationCfg - > textColor & 0xFF , ( m_pRecognizationCfg - > textColor & 0xFF00 ) > > 8 , ( m_pRecognizationCfg - > textColor & 0xFF0000 ) > > 16 ) ;
float minSizeW = m_pRecognizationCfg - > minSize > 0 ? ( photoInfo . width * m_pRecognizationCfg - > minSize / 100 ) : 0 ;
float minSizeH = m_pRecognizationCfg - > minSize > 0 ? ( photoInfo . height * m_pRecognizationCfg - > minSize / 100 ) : 0 ;
for ( std : : vector < IDevice : : RECOG_OBJECT > : : const_iterator it = objs . cbegin ( ) ; it ! = objs . cend ( ) ; )
{
if ( it - > label > = m_pRecognizationCfg - > items . size ( ) )
{
it = objs . erase ( it ) ;
continue ;
}
const IDevice : : CFG_RECOGNIZATION : : ITEM & item = m_pRecognizationCfg - > items [ it - > label ] ;
if ( item . enabled = = 0 | | it - > prob < item . prob )
{
it = objs . erase ( it ) ;
continue ;
}
if ( m_pRecognizationCfg - > minSize > 0 )
{
if ( it - > w < minSizeW | | it - > h < minSizeH )
{
it = objs . erase ( it ) ;
continue ;
}
}
if ( ( photoInfo . recognization & 0x2 ) ! = 0 )
{
cv : : Rect rc ( it - > x , it - > y , it - > w , it - > h ) ;
cv : : rectangle ( mat , rc , borderColor , m_pRecognizationCfg - > thickness ) ;
textSize = ft2 - > getTextSize ( item . name , fontSize , thickness , & baseline ) ;
textSize . height + = baseline ;
if ( it - > y > textSize . height )
{
pt . y = it - > y - textSize . height - 4 - m_pRecognizationCfg - > thickness ;
}
else if ( mat . rows - it - > y - it - > h > textSize . height )
{
pt . y = it - > y + it - > h + 4 + m_pRecognizationCfg - > thickness ;
}
else
{
// Inner
pt . y = it - > y + 4 + m_pRecognizationCfg - > thickness ;
}
if ( mat . cols - it - > x > textSize . width )
{
pt . x = it - > x ;
}
else
{
pt . x = it - > x + it - > w - textSize . width ;
}
# ifdef OUTPUT_CAMERA_DBG_INFO
char buf [ 128 ] ;
snprintf ( buf , sizeof ( buf ) , " AI: %d=%s (%f,%f)-(%f,%f) Text:(%d,%d)-(%d,%d) " ,
it - > label , item . name . c_str ( ) , it - > x , it - > y , it - > w , it - > h , pt . x , pt . y , textSize . width , textSize . height ) ;
XYLOG ( XYLOG_SEVERITY_DEBUG , buf ) ;
# endif
ft2 - > putText ( mat , item . name + std : : to_string ( ( int ) ( it - > prob * 100.0 ) ) + " % " , pt , fontSize , textColor , thickness , cv : : LINE_AA , false , true ) ;
}
+ + it ;
}
}
}
else
{
XYLOG ( XYLOG_SEVERITY_WARNING , " Channel AI Disabled " ) ;
}
// #ifdef OUTPUT_CAMERA_DBG_INFO
if ( ! cameraInfo . empty ( ) )
{
// NdkCamera::CAPTURE_RESULT captureResult = mCamera->getCaptureResult();
if ( photoInfo . outputDbgInfo ! = 0 )
{
cv : : Scalar scalarRed ( 0 , 0 , 255 ) ; // red
int fs = fontSize * 2 / 3 ;
textSize = ft2 - > getTextSize ( cameraInfo , fs , - 1 , & baseline ) ;
cv : : Point lt ( 0 , mat . rows - fs - 20 * ratio ) ;
cv : : Point lt2 ( 0 , lt . y - 2 * ratio ) ;
cv : : Point rb ( 0 + textSize . width + 2 * ratio , lt2 . y + textSize . height + 8 * ratio ) ;
if ( rb . x > ( int ) width - 1 )
{
rb . x = ( int ) width - 1 ;
}
if ( rb . y > ( int ) height - 1 )
{
rb . y = ( int ) height - 1 ;
}
cv : : Mat roi = mat ( cv : : Rect ( lt2 , rb ) ) ;
cv : : Mat clrMat ( roi . size ( ) , CV_8UC3 , scalarWhite ) ;
double alpha = 0.5 ;
cv : : addWeighted ( clrMat , alpha , roi , 1.0 - alpha , 0.0 , roi ) ;
// cv::rectangle(mat, lt2, rb,cv::Scalar(255, 255, 255), -1);
ft2 - > putText ( mat , cameraInfo , lt , fs , scalarRed , - 1 , cv : : LINE_AA , false ) ;
// DrawOutlineText(ft2, mat, str, cv::Point(0, mat.rows - fs - 20 * ratio), fs, scalarWhite, 1);
}
}
// #endif // OUTPUT_CAMERA_DBG_INFO
for ( vector < OSD_INFO > : : const_iterator it = osds . cbegin ( ) ; it ! = osds . cend ( ) ; + + it )
{
if ( it - > text . empty ( ) )
{
continue ;
}
# ifdef _DEBUG
if ( it - > alignment = = OSD_ALIGNMENT_BOTTOM_RIGHT )
{
int aa = 0 ;
}
# endif
textSize = ft2 - > getTextSize ( it - > text , fontSize , thickness , & baseline ) ;
XYLOG ( XYLOG_SEVERITY_DEBUG , " %s font Size=%d height: %d baseline=%d " , it - > text . c_str ( ) , fontSize , textSize . height , baseline ) ;
if ( it - > alignment = = OSD_ALIGNMENT_TOP_LEFT )
{
pt . x = it - > x * ratio ;
pt . y = it - > y * ratio ;
}
else if ( it - > alignment = = OSD_ALIGNMENT_TOP_RIGHT )
{
pt . x = width - textSize . width - it - > x * ratio ;
pt . y = it - > y * ratio ;
}
else if ( it - > alignment = = OSD_ALIGNMENT_BOTTOM_RIGHT )
{
pt . x = width - textSize . width - it - > x * ratio ;
pt . y = height - it - > y * ratio - textSize . height - baseline ;
}
else if ( it - > alignment = = OSD_ALIGNMENT_BOTTOM_LEFT )
{
pt . x = it - > x * ratio ;
pt . y = height - it - > y * ratio - textSize . height - baseline ;
}
// cv::Rect rc(pt.x, pt.y, textSize.width, textSize.height);
// cv::rectangle(mat, rc, cv::Scalar(0,255,255), 2);
DrawOutlineText ( ft2 , mat , it - > text , pt , fontSize , scalarWhite , thickness ) ;
}
std : : vector < int > params ;
params . push_back ( cv : : IMWRITE_JPEG_QUALITY ) ;
params . push_back ( ( int ) ( ( uint32_t ) photoInfo . quality ) ) ;
bool res = false ;
std : : string fullPath = endsWith ( path , " .jpg " ) ? path : ( path + CTerminal : : BuildPhotoFileName ( photoInfo ) ) ;
if ( ! std : : filesystem : : exists ( std : : filesystem : : path ( fullPath ) ) )
{
# ifdef _DEBUG
char log [ 256 ] = { 0 } ;
strcpy ( log , fullPath . c_str ( ) ) ;
# endif
bool res = cv : : imwrite ( fullPath . c_str ( ) , mat , params ) ;
if ( ! res )
{
XYLOG ( XYLOG_SEVERITY_ERROR , " Failed to Write File: %s " , fullPath . c_str ( ) + m_appPath . size ( ) ) ;
}
else
{
XYLOG ( XYLOG_SEVERITY_INFO , " Succeeded to Write File: %s " , fullPath . c_str ( ) + m_appPath . size ( ) ) ;
}
TakePhotoCb ( res ? 2 : 0 , photoInfo , fullPath , photoInfo . photoTime , objs ) ;
}
else
{
XYLOG ( XYLOG_SEVERITY_INFO , " Photo File Exists: %s " , fullPath . c_str ( ) + m_appPath . size ( ) ) ;
}
return res ;
}
bool CPhoneDevice : : OnCaptureReady ( bool photoOrVideo , bool result , cv : : Mat & mat , unsigned int photoId )
{
XYLOG ( XYLOG_SEVERITY_INFO , " RAW Capture finished: %u RES=%d " , photoId , ( result ? 1 : 0 ) ) ;
if ( photoOrVideo )
{
if ( result )
{
OnImageReady ( mat ) ;
}
else
{
std : : vector < IDevice : : RECOG_OBJECT > objs ;
TakePhotoCb ( 0 , mPhotoInfo , " " , time ( NULL ) , objs ) ;
CPhoneCamera * pCamera = mCamera ;
mCamera = NULL ;
bool turnOffOtg = ( mPhotoInfo . usbCamera ! = 0 ) ;
std : : thread closeThread ( & CPhoneDevice : : CloseCamera2 , this , pCamera , mPhotoInfo . photoId , mPhotoInfo . cameraType ) ;
m_threadClose . swap ( closeThread ) ;
if ( closeThread . joinable ( ) )
{
closeThread . detach ( ) ;
}
}
}
return true ;
}
bool CPhoneDevice : : OnVideoReady ( bool photoOrVideo , bool result , const char * path , unsigned int photoId )
{
if ( photoOrVideo )
{
mPhotoInfo . photoTime = time ( NULL ) ;
CPhoneCamera * pCamera = NULL ;
std : : vector < IDevice : : RECOG_OBJECT > objs ;
std : : string fullPath = mPath + CTerminal : : BuildPhotoFileName ( mPhotoInfo ) ;
if ( result )
{
std : : rename ( path , fullPath . c_str ( ) ) ;
}
TakePhotoCb ( result ? 3 : 0 , mPhotoInfo , fullPath , time ( NULL ) , objs ) ;
bool turnOffOtg = ( mPhotoInfo . usbCamera ! = 0 ) ;
std : : thread closeThread ( & CPhoneDevice : : CloseCamera2 , this , pCamera , mPhotoInfo . photoId , mPhotoInfo . cameraType ) ;
m_threadClose . swap ( closeThread ) ;
}
else
{
mPhotoInfo . photoTime = time ( NULL ) ;
CPhoneCamera * pCamera = NULL ;
std : : vector < IDevice : : RECOG_OBJECT > objs ;
std : : string fullPath = mPath + CTerminal : : BuildPhotoFileName ( mPhotoInfo ) ;
if ( result )
{
std : : rename ( path , fullPath . c_str ( ) ) ;
}
TakePhotoCb ( result ? 3 : 0 , mPhotoInfo , fullPath , time ( NULL ) , objs ) ;
bool turnOffOtg = ( mPhotoInfo . usbCamera ! = 0 ) ;
std : : thread closeThread ( & CPhoneDevice : : CloseCamera2 , this , pCamera , mPhotoInfo . photoId , mPhotoInfo . cameraType ) ;
m_threadClose . swap ( closeThread ) ;
}
return result ;
}
void CPhoneDevice : : onError ( const std : : string & msg )
{
if ( mCamera = = NULL )
{
int aa = 0 ;
return ;
}
XYLOG ( XYLOG_SEVERITY_ERROR , " Failed to Take Photo (IMGID=%u): %s " , mPhotoInfo . photoId , msg . c_str ( ) ) ;
CPhoneCamera * pCamera = mCamera ;
mCamera = NULL ;
TakePhotoCb ( 0 , mPhotoInfo , mPath , 0 ) ;
bool turnOffOtg = ( mPhotoInfo . usbCamera ! = 0 ) ;
std : : thread closeThread ( & CPhoneDevice : : CloseCamera2 , this , pCamera , mPhotoInfo . photoId , mPhotoInfo . cameraType ) ;
// closeThread.detach();
m_threadClose . swap ( closeThread ) ;
}
void CPhoneDevice : : onDisconnected ( ACameraDevice * device )
{
if ( mCamera = = NULL )
{
return ;
}
XYLOG ( XYLOG_SEVERITY_ERROR , " Failed to Take Photo (IMGID=%u) as for Disconnection " , mPhotoInfo . photoId ) ;
CPhoneCamera * pCamera = mCamera ;
mCamera = NULL ;
TakePhotoCb ( 0 , mPhotoInfo , mPath , 0 ) ;
bool turnOffOtg = ( mPhotoInfo . usbCamera ! = 0 ) ;
std : : thread closeThread ( & CPhoneDevice : : CloseCamera2 , this , pCamera , mPhotoInfo . photoId , mPhotoInfo . cameraType ) ;
// closeThread.detach();
m_threadClose . swap ( closeThread ) ;
}
std : : string CPhoneDevice : : GetFileName ( ) const
{
return mPath ;
}
std : : string CPhoneDevice : : GetVersion ( ) const
{
// FOR OSD
string version = std : : to_string ( mVersionCode / 100000 ) ;
version + = " . " ;
version + = std : : to_string ( ( mVersionCode % 100000 ) / 1000 ) ;
version + = " . " ;
version + = std : : to_string ( mVersionCode % 1000 ) ;
return version ;
}
void CPhoneDevice : : UpdatePosition ( double lon , double lat , double radius , time_t ts )
{
if ( m_listener ! = NULL )
{
if ( shouldConvertPosition ( lat , lon ) )
{
transformPosition ( lat , lon ) ;
}
return m_listener - > OnPositionDataArrived ( lon , lat , radius , ts ) ;
}
}
void CPhoneDevice : : UpdateSignalLevel ( int signalLevel )
{
m_signalLevel = signalLevel ;
m_signalLevelUpdateTime = time ( NULL ) ;
}
void CPhoneDevice : : UpdateSimcard ( const std : : string & simcard )
{
m_simcard = simcard ;
}
void CPhoneDevice : : UpdateEthernet ( net_handle_t nethandle , bool available )
{
m_devLocker . lock ( ) ;
m_netHandle = available ? nethandle : NETWORK_UNSPECIFIED ;
m_devLocker . unlock ( ) ;
XYLOG ( XYLOG_SEVERITY_WARNING , " NET Handle: %lld " , available ? ( uint64_t ) nethandle : 0 ) ;
}
net_handle_t CPhoneDevice : : GetNetHandle ( ) const
{
net_handle_t nethandle = NETWORK_UNSPECIFIED ;
m_devLocker . lock ( ) ;
nethandle = m_netHandle ;
m_devLocker . unlock ( ) ;
return nethandle ;
}
void CPhoneDevice : : SetStaticIp ( const std : : string & iface , const std : : string & ip , const std : : string & netmask , const std : : string & gateway )
{
JNIEnv * env = NULL ;
jboolean ret = JNI_FALSE ;
bool didAttachThread = false ;
bool res = GetJniEnv ( m_vm , & env , didAttachThread ) ;
if ( ! res )
{
ALOGE ( " Failed to get JNI Env " ) ;
}
jstring jiface = env - > NewStringUTF ( iface . c_str ( ) ) ;
# ifdef USING_N938
jstring jip = env - > NewStringUTF ( " 0.0.0.0 " ) ;
# else
jstring jip = env - > NewStringUTF ( ip . c_str ( ) ) ;
# endif
jstring jnetmask = env - > NewStringUTF ( netmask . c_str ( ) ) ;
jstring jgw = env - > NewStringUTF ( gateway . c_str ( ) ) ;
env - > CallVoidMethod ( m_javaService , mSetStaticIpMid , jiface , jip , jnetmask , jgw ) ;
// env->DeleteLocalRef(jgw);
// env->DeleteLocalRef(jnetmask);
// env->DeleteLocalRef(jip);
// env->DeleteLocalRef(jiface);
if ( didAttachThread )
{
m_vm - > DetachCurrentThread ( ) ;
}
}
int CPhoneDevice : : GetIceData ( IDevice : : ICE_INFO * iceInfo , IDevice : : ICE_TAIL * iceTail , SENSOR_PARAM * sensorParam )
{
m_tempData . instantaneous_windspeed = 0xff ;
m_tempData . air_temperature = 0xff ;
m_tempData . instantaneous_winddirection = 0xff ;
m_tempData . humidity = 0xff ;
std : : unique_lock < std : : mutex > lock ( m_collectDataLocker ) ;
if ( ! m_collecting . load ( ) ) {
m_collecting . store ( true ) ;
m_CollectDatacv . notify_all ( ) ;
lock . unlock ( ) ;
Collect_sensor_data ( ) ; //15s
lock . lock ( ) ;
m_collecting . store ( false ) ;
m_CollectDatacv . notify_all ( ) ;
} else {
m_CollectDatacv . wait ( lock , [ this ] { return ! m_collecting . load ( ) ; } ) ;
// m_collecting.store(false);
}
Data_DEF airt ;
//++等值覆冰厚度, 综合悬挂载荷, 不均衡张力差 置0
iceInfo - > equal_icethickness = 0xff ;
iceInfo - > tension = 0xff ;
iceInfo - > tension_difference = 0xff ;
bool status = 1 ;
int pullno = 0 ;
int angleno = 0 ;
for ( int num = 0 ; num < MAX_SERIAL_DEV_NUM ; num + + )
{
if ( sensorParam [ num ] . SensorsType = = RALLY_PROTOCOL & & sensorParam [ num ] . IsNoInsta = = 1 )
{
GetPullValue ( num , & airt ) ;
iceInfo - > t_sensor_data [ pullno ] . original_tension = airt . EuValue ;
XYLOG ( XYLOG_SEVERITY_INFO , " 地址%d,采样状态 = %d,拉力 = %f " , sensorParam [ num ] . devaddr , airt . AiState , iceInfo - > t_sensor_data [ pullno ] . original_tension ) ;
if ( airt . AiState ! = 2 & & iceInfo - > t_sensor_data [ pullno ] . original_tension = = 0 )
{
XYLOG ( XYLOG_SEVERITY_INFO , " 地址%d,采样状态 = %d,拉力未采集到数据,重新采样 " , sensorParam [ num ] . devaddr , airt . AiState ) ;
status = 0 ;
}
pullno + + ;
} else if ( sensorParam [ num ] . SensorsType = = SLANT_PROTOCOL & & sensorParam [ num ] . IsNoInsta = = 1 )
{
GetAngleValue ( num , & airt , 0 ) ;
iceInfo - > t_sensor_data [ angleno ] . deflection_angle = airt . EuValue ;
XYLOG ( XYLOG_SEVERITY_INFO , " 地址%d,采样状态 = %d,x = %f " , sensorParam [ num ] . devaddr , airt . AiState , iceInfo - > t_sensor_data [ angleno ] . deflection_angle ) ;
if ( airt . AiState ! = 2 & & iceInfo - > t_sensor_data [ angleno ] . deflection_angle = = 0 )
{
XYLOG ( XYLOG_SEVERITY_INFO , " 地址%d,采样状态 = %d,倾角x未采集到数据,重新采样 " , sensorParam [ num ] . devaddr , airt . AiState ) ;
status = 0 ;
}
GetAngleValue ( num , & airt , 1 ) ;
iceInfo - > t_sensor_data [ angleno ] . windage_yaw_angle = airt . EuValue ;
XYLOG ( XYLOG_SEVERITY_INFO , " 地址%d,采样状态 = %d,y = %f " , sensorParam [ num ] . devaddr , airt . AiState , iceInfo - > t_sensor_data [ angleno ] . windage_yaw_angle ) ;
if ( airt . AiState ! = 2 & & iceInfo - > t_sensor_data [ angleno ] . windage_yaw_angle = = 0 )
{
XYLOG ( XYLOG_SEVERITY_INFO , " 地址%d,采样状态 = %d,倾角y未采集到数据,重新采样 " , sensorParam [ num ] . devaddr , airt . AiState ) ;
status = 0 ;
}
angleno + + ;
}
}
{
std : : lock_guard < std : : mutex > lock ( m_dataLocker ) ;
GetWindSpeedData ( & airt ) ;
iceTail - > instantaneous_windspeed = airt . EuValue ;
if ( airt . AiState ! = 2 & & iceTail - > instantaneous_windspeed = = 0 & & m_tempData . instantaneous_windspeed = = 0xff )
{
XYLOG ( XYLOG_SEVERITY_INFO , " 采样状态 = %d,覆冰风速未采集到数据,重新采样 " , airt . AiState ) ;
status = 0 ;
} else if ( airt . AiState = = 2 & & m_tempData . instantaneous_windspeed = = 0xff )
{
m_tempData . instantaneous_windspeed = iceTail - > instantaneous_windspeed ;
} else if ( iceTail - > instantaneous_windspeed = = 0 & & m_tempData . instantaneous_windspeed ! = 0xff )
{
iceTail - > instantaneous_windspeed = m_tempData . instantaneous_windspeed ;
}
GetWindDirectionData ( & airt ) ;
iceTail - > instantaneous_winddirection = airt . EuValue ;
if ( airt . AiState ! = 2 & & iceTail - > instantaneous_winddirection = = 0 & & m_tempData . instantaneous_winddirection = = 0xff )
{
XYLOG ( XYLOG_SEVERITY_INFO , " 采样状态 = %d,覆冰风向未采集到数据,重新采样 " , airt . AiState ) ;
status = 0 ;
} else if ( airt . AiState = = 2 & & m_tempData . instantaneous_winddirection = = 0xff )
{
m_tempData . instantaneous_winddirection = iceTail - > instantaneous_winddirection ;
} else if ( iceTail - > instantaneous_winddirection = = 0 & & m_tempData . instantaneous_winddirection ! = 0xff )
{
iceTail - > instantaneous_winddirection = m_tempData . instantaneous_winddirection ;
}
GetAirTempData ( & airt ) ;
iceTail - > air_temperature = airt . EuValue ;
if ( airt . AiState ! = 2 & & iceTail - > air_temperature = = 0 & & m_tempData . air_temperature = = 0xff )
{
XYLOG ( XYLOG_SEVERITY_INFO , " 采样状态 = %d,覆冰温度未采集到数据,重新采样 " , airt . AiState ) ;
status = 0 ;
} else if ( airt . AiState = = 2 & & m_tempData . air_temperature = = 0xff )
{
m_tempData . air_temperature = iceTail - > air_temperature ;
} else if ( iceTail - > air_temperature = = 0 & & m_tempData . air_temperature ! = 0xff )
{
iceTail - > air_temperature = m_tempData . air_temperature ;
}
GetHumidityData ( & airt ) ;
iceTail - > humidity = airt . EuValue ;
if ( airt . AiState ! = 2 & & iceTail - > humidity = = 0 & & m_tempData . humidity = = 0xff )
{
XYLOG ( XYLOG_SEVERITY_INFO , " 采样状态 = %d,覆冰湿度未采集到数据,重新采样 " , airt . AiState ) ;
status = 0 ;
} else if ( airt . AiState = = 2 & & m_tempData . humidity = = 0xff )
{
m_tempData . humidity = iceTail - > humidity ;
} else if ( iceTail - > humidity = = 0 & & m_tempData . humidity ! = 0xff )
{
iceTail - > humidity = m_tempData . humidity ;
}
}
if ( status )
return true ;
else
return false ;
}
int CPhoneDevice : : GetWData ( IDevice : : WEATHER_INFO * weatherInfo )
{
m_tempData . instantaneous_windspeed = 0xff ;
m_tempData . air_temperature = 0xff ;
m_tempData . instantaneous_winddirection = 0xff ;
m_tempData . humidity = 0xff ;
bool status = 1 ;
std : : unique_lock < std : : mutex > lock ( m_collectDataLocker ) ;
if ( ! m_collecting . load ( ) ) {
m_collecting . store ( true ) ;
m_CollectDatacv . notify_all ( ) ;
lock . unlock ( ) ;
Collect_sensor_data ( ) ; //15s
lock . lock ( ) ;
m_collecting . store ( false ) ;
m_CollectDatacv . notify_all ( ) ;
} else {
m_CollectDatacv . wait ( lock , [ this ] { return ! m_collecting . load ( ) ; } ) ;
// m_collecting.store(false);
}
Data_DEF airt ;
{
std : : lock_guard < std : : mutex > lock ( m_dataLocker ) ;
GetWeatherData ( & airt , 2 ) ;
weatherInfo - > avg_windspeed_10min = airt . EuValue ;
weatherInfo - > extreme_windspeed = airt . EuValue ;
weatherInfo - > standard_windspeed = airt . EuValue ;
if ( airt . AiState ! = 2 & & weatherInfo - > avg_windspeed_10min = = 0 & &
m_tempData . instantaneous_windspeed = = 0xff )
{
XYLOG ( XYLOG_SEVERITY_INFO , " 采样状态 = %d,气象风速未采集到数据,重新采样 " , airt . AiState ) ;
status = 0 ;
} else if ( airt . AiState = = 2 & & m_tempData . instantaneous_windspeed = = 0xff )
{
m_tempData . instantaneous_windspeed = weatherInfo - > avg_windspeed_10min ;
} else if ( weatherInfo - > avg_windspeed_10min = = 0 & & m_tempData . instantaneous_windspeed ! = 0xff )
{
weatherInfo - > avg_windspeed_10min = m_tempData . instantaneous_windspeed ;
weatherInfo - > extreme_windspeed = m_tempData . instantaneous_windspeed ;
weatherInfo - > standard_windspeed = m_tempData . instantaneous_windspeed ;
}
GetWeatherData ( & airt , 3 ) ;
weatherInfo - > avg_winddirection_10min = airt . EuValue ;
if ( airt . AiState ! = 2 & & weatherInfo - > avg_winddirection_10min = = 0 & &
m_tempData . instantaneous_winddirection = = 0xff )
{
XYLOG ( XYLOG_SEVERITY_INFO , " 采样状态 = %d,气象风向未采集到数据,重新采样 " , airt . AiState ) ;
status = 0 ;
} else if ( airt . AiState = = 2 & & m_tempData . instantaneous_winddirection = = 0xff )
{
m_tempData . instantaneous_winddirection = weatherInfo - > avg_winddirection_10min ;
} else if ( weatherInfo - > winddirection = = 0 & & m_tempData . instantaneous_winddirection ! = 0xff )
{
weatherInfo - > winddirection = m_tempData . instantaneous_winddirection ;
}
GetWeatherData ( & airt , 0 ) ;
weatherInfo - > air_temperature = airt . EuValue ;
if ( airt . AiState ! = 2 & & weatherInfo - > air_temperature = = 0 & &
m_tempData . air_temperature = = 0xff )
{
XYLOG ( XYLOG_SEVERITY_INFO , " 采样状态 = %d,气象温度未采集到数据,重新采样 " , airt . AiState ) ;
status = 0 ;
} else if ( airt . AiState = = 2 & & m_tempData . air_temperature = = 0xff )
{
m_tempData . air_temperature = weatherInfo - > air_temperature ;
} else if ( weatherInfo - > air_temperature = = 0 & & m_tempData . air_temperature ! = 0xff )
{
weatherInfo - > air_temperature = m_tempData . air_temperature ;
}
GetWeatherData ( & airt , 1 ) ;
weatherInfo - > humidity = airt . EuValue ;
if ( airt . AiState ! = 2 & & weatherInfo - > humidity = = 0 & & m_tempData . humidity = = 0xff )
{
XYLOG ( XYLOG_SEVERITY_INFO , " 采样状态 = %d,气象湿度未采集到数据,重新采样 " , airt . AiState ) ;
status = 0 ;
} else if ( airt . AiState = = 2 & & m_tempData . humidity = = 0xff )
{
m_tempData . humidity = weatherInfo - > humidity ;
} else if ( weatherInfo - > humidity = = 0 & & m_tempData . humidity ! = 0xff )
{
weatherInfo - > humidity = m_tempData . humidity ;
}
GetWeatherData ( & airt , 4 ) ;
weatherInfo - > precipitation = airt . EuValue ;
// if (airt.AiState != 2 && weatherInfo->precipitation == 0) {
// XYLOG(XYLOG_SEVERITY_INFO, "采样状态 = %d,降雨量未采集到数据,重新采样",
// weatherInfo->precipitation, airt.AiState);
// status = 0;
// }
GetWeatherData ( & airt , 5 ) ;
weatherInfo - > air_pressure = airt . EuValue ;
// if (airt.AiState != 2 && weatherInfo->air_pressure == 0) {
// XYLOG(XYLOG_SEVERITY_INFO, "采样状态 = %d,气压未采集到数据,重新采样",
// weatherInfo->air_pressure, airt.AiState);
// status = 0;
// }
GetWeatherData ( & airt , 6 ) ;
weatherInfo - > radiation_intensity = airt . EuValue ;
// if (airt.AiState != 2 && weatherInfo->radiation_intensity == 0) {
// XYLOG(XYLOG_SEVERITY_INFO, "采样状态 = %d,光照强度未采集到数据,重新采样",
// weatherInfo->radiation_intensity, airt.AiState);
// status = 0;
// }
if ( status )
return true ;
else
return false ;
}
}
bool CPhoneDevice : : OpenSensors ( int sensortype )
{
if ( sensortype = = MAIN_POWER_OPEN ) {
GpioControl : : set12VEnable ( true ) ;
GpioControl : : setCam3V3Enable ( true ) ;
GpioControl : : setRS485Enable ( true ) ;
GpioControl : : TurnOn ( CMD_SET_SPI_POWER ) ;
// GpioControl::TurnOn(CMD_SET_485_EN_STATE); // 打开RS485电源
# ifndef USING_N938
# ifndef USING_PLZ
GpioControl : : TurnOn ( CMD_SET_485_EN_STATE ) ;
# else
GpioControl : : TurnOn ( CMD_SET_485_ENABLE ) ;
# endif
# else
GpioControl : : TurnOn ( CMD_SPI2SERIAL_POWER_EN ) ;
GpioControl : : TurnOn ( CMD_RS485_3V3_EN ) ;
# endif
}
if ( sensortype = = CAMERA_SENSOR_OPEN )
{
# ifndef USING_N938
# ifndef USING_PLZ
# else
GpioControl : : TurnOn ( CMD_SET_PTZ_PWR_ENABLE ) ;
# endif
# else
GpioControl : : TurnOn ( CMD_SET_PIC1_POWER ) ;
GpioControl : : TurnOn ( CMD_SET_485_EN4 ) ;
# endif
// GpioControl::TurnOn(CMD_SET_CAM_3V3_EN_STATE); // 打开3.3V电压
// GpioControl::TurnOn(CMD_SET_3V3_PWR_ENABLE);
}
if ( sensortype = = WEATHER_SENSOR_OPEN )
{
# ifndef USING_N938
# else
GpioControl : : TurnOn ( CMD_SET_WTH_POWER ) ;
GpioControl : : TurnOn ( CMD_SET_485_EN3 ) ;
# endif
}
if ( sensortype = = ICETHICK_SENSOR_OPEN )
{
# ifndef USING_N938
# else
GpioControl : : TurnOn ( CMD_SET_PULL_POWER ) ;
GpioControl : : TurnOn ( CMD_SET_ANGLE_POWER ) ;
GpioControl : : TurnOn ( CMD_SET_485_EN1 ) ;
GpioControl : : TurnOn ( CMD_SET_485_EN0 ) ;
# endif
}
if ( sensortype = = OTHER_SENSOR )
{
# ifndef USING_N938
# else
GpioControl : : TurnOn ( CMD_SET_OTHER_POWER ) ;
GpioControl : : TurnOn ( CMD_SET_485_EN2 ) ;
# endif
}
return 0 ;
}
bool CPhoneDevice : : CloseSensors ( int sensortype )
{
if ( sensortype = = MAIN_POWER_OPEN )
{
GpioControl : : TurnOff ( CMD_SET_SPI_POWER ) ;
GpioControl : : set12VEnable ( false ) ;
GpioControl : : setCam3V3Enable ( false ) ;
GpioControl : : setRS485Enable ( false ) ;
// GpioControl::TurnOff(CMD_SET_485_EN_STATE);
# ifndef USING_N938
# ifndef USING_PLZ
GpioControl : : TurnOff ( CMD_SET_485_EN_STATE ) ;
# else
GpioControl : : TurnOff ( CMD_SET_485_ENABLE ) ;
# endif
# else
GpioControl : : TurnOff ( CMD_SPI2SERIAL_POWER_EN ) ;
GpioControl : : TurnOff ( CMD_RS485_3V3_EN ) ;
# endif
}
if ( sensortype = = CAMERA_SENSOR_OPEN )
{
# ifdef USING_N938
GpioControl : : TurnOff ( CMD_SET_PIC1_POWER ) ;
GpioControl : : TurnOff ( CMD_SET_485_EN4 ) ;
// GpioControl::TurnOff(CMD_SET_CAM_3V3_EN_STATE);
# endif
# ifndef USING_N938
// GpioControl::TurnOff(CMD_SET_3V3_PWR_ENABLE);
# ifndef USING_PLZ
# else
GpioControl : : TurnOff ( CMD_SET_PTZ_PWR_ENABLE ) ;
# endif
# endif
}
if ( sensortype = = WEATHER_SENSOR_OPEN )
{
# ifndef USING_N938
# else
GpioControl : : TurnOff ( CMD_SET_WTH_POWER ) ;
GpioControl : : TurnOff ( CMD_SET_485_EN3 ) ;
# endif
}
if ( sensortype = = ICETHICK_SENSOR_OPEN )
{
# ifndef USING_N938
# else
GpioControl : : TurnOff ( CMD_SET_PULL_POWER ) ;
GpioControl : : TurnOff ( CMD_SET_ANGLE_POWER ) ;
GpioControl : : TurnOff ( CMD_SET_485_EN1 ) ;
GpioControl : : TurnOff ( CMD_SET_485_EN0 ) ;
# endif
}
if ( sensortype = = OTHER_SENSOR )
{
# ifndef USING_N938
# else
GpioControl : : TurnOff ( CMD_SET_OTHER_POWER ) ;
GpioControl : : TurnOff ( CMD_SET_485_EN2 ) ;
# endif
}
return 0 ;
}
bool CPhoneDevice : : LoadNetworkInfo ( )
{
std : : vector < uint8_t > content ;
if ( ! readFile ( m_appPath + ( APP_PATH_NETWORK ) , content ) & & ! content . empty ( ) )
{
return false ;
}
Json : : CharReaderBuilder builder ;
std : : unique_ptr < Json : : CharReader > reader ( builder . newCharReader ( ) ) ;
Json : : Value jsonVal ;
const char * doc = ( const char * ) & ( content [ 0 ] ) ;
std : : string errMsg ;
if ( ! reader - > parse ( doc , doc + content . size ( ) , & jsonVal , & errMsg ) )
{
return false ;
}
if ( m_network = = NULL )
{
m_network = new NETWORK ( ) ;
}
GetJSONValue ( jsonVal , " iface " , m_network - > iface ) ;
GetJSONValue ( jsonVal , " ip " , m_network - > ip ) ;
GetJSONValue ( jsonVal , " netmask " , m_network - > netmask ) ;
GetJSONValue ( jsonVal , " gateway " , m_network - > gateway ) ;
return true ;
}
void CPhoneDevice : : SetStaticIp ( )
{
if ( m_network ! = NULL )
{
SetStaticIp ( m_network - > iface , m_network - > ip , m_network - > netmask , m_network - > gateway ) ;
XYLOG ( XYLOG_SEVERITY_INFO , " Set Static IP on %s: %s " , m_network - > iface . c_str ( ) ,
m_network - > ip . c_str ( ) ) ;
}
else
{
# ifdef USING_N938
SetStaticIp ( " eth0 " , " 0.0.0.0 " , " 255.255.255.0 " , " 192.168.1.1 " ) ;
# endif
XYLOG ( XYLOG_SEVERITY_WARNING , " No Static IP Confg " ) ;
}
}