活动介绍

This+application+has+no+configured+error+view

时间: 2023-11-12 20:03:32 浏览: 283
这个错误通常出现在使用某些框架或库时,当应用程序出现错误时,它会尝试显示一个错误视图,但是由于没有正确配置,所以会出现"This application has no configured error view"的错误信息。 要解决这个问题,需要根据具体情况进行调试和排查。以下是一些可能的解决方法: 1. 检查应用程序的配置文件,确保已正确配置错误视图。 2. 检查应用程序的依赖项,确保它们已正确安装和配置。 3. 检查应用程序的代码,查找可能导致错误视图无法正常工作的问题。 4. 如果使用的是某个框架或库,可以查看它们的文档或社区论坛,寻求帮助和解决方案。
相关问题

This application has no configured error view, so you are seeing this as a fallback

这个错误信息是由于应用程序没有配置错误视图而导致的。这意味着当应用程序遇到错误时,它无法显示一个友好的错误页面。通常,这种情况下,应用程序会返回一个 HTTP 状态码和一些错误信息,但是没有更多的信息来帮助用户解决问题。 为了解决这个问题,你需要配置一个错误视图,以便在应用程序遇到错误时,能够显示一个友好的错误页面。这个页面应该包含一些有用的信息,例如错误代码、错误消息和可能的解决方案。

This application has no configured error view, so you are seeing this as a fallback.

引用和中提到了"This application has no configured error view, so you are seeing this as a fallback."这个错误提示。这个错误提示意味着应用程序没有配置错误视图,所以你看到了这个默认的回退页面。这通常发生在应用程序无法找到所请求的页面的情况下,比如在请求一个不存在的页面时会出现404错误。引用中也提到了这个错误提示,说明在预约挂号系统的前端遇到了一个小bug,最后发现是用户登录模块没有注册导致的。所以这个错误提示通常表示应用程序在处理请求时发生了错误,并且没有相应的错误视图来显示给用户。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SpringCloudAlibaba2021 网关访问错误解决](https://blog.csdn.net/m290345792/article/details/125219030)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [spring-cloud-gateway 网关自定义异常处理](https://blog.csdn.net/jilo88/article/details/125078951)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [YYGH-BUG-01](https://blog.csdn.net/weixin_53227758/article/details/123940207)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
阅读全文

相关推荐

<?xml version="1.0" encoding="utf-8"?> <resources> <string name="error__6">Operation failed. Please try later.</string> <string name="error_263">No default tenant found, please contact service provider.</string> <string name="error__107">Failed to connect to the camera. Try again later.</string> <string name="error_004">Invalid email address.</string> <string name="error_006">Incorrect mobile number.</string> <string name="error_009">The phone number has already been registered once, please use another number or use this number to login.</string> <string name="error_010">Incorrect verification code.</string> <string name="error_011">The email address has been bound.</string> <string name="error_012">Failed to log in to the app. Please log in again.</string> <string name="error_018">Invalid application ID.</string> <string name="error_019">Invalid operation.</string> <string name="error_024">Invalid plug-in.</string> <string name="error_025">Operation failed. Please try later.</string> <string name="error_026">Plug-in does not exist.</string> <string name="error_027">Failed to log in to the app. Please log in again.</string> <string name="error_030">The terminal has been bound.</string> <string name="error_031">Operation failed. Please try later.</string> <string name="error_032">The terminal does not bind to this account.</string> <string name="error_033">Terminals are being operated by other users.</string> <string name="error_034">Operation failed. Please try later.</string> <string name="error_035">Failed to obtain the application list.</string> <string name="error_036">Failed to obtain the application image.</string> <string name="error_037">Failed to obtain the application version.</string> <string name="error_038">Failed to obtain the Wi-Fi coverage information.</string> <string name="error_040">The email address has not been bound to an account.</string> <string name="error_042">Operation failed. Please try later.</string> <string name="error_044">Operation failed. Please try later.</string> <string name="error_048">Operation failed. Please try later.</string> <string name="error_050">Operation failed. Please try later.</string> <string name="error_051">Operation failed. Please try later.</string> <string name="error_056">Configuration page query failed.</string> <string name="error_057">Operation failed. Please try later.</string> <string name="error_058">Plug-in list query failed.</string> <string name="error_059">Plug-in image query failed.</string> <string name="error_060">Operation failed. Please try later.</string> <string name="error_061">Operation failed. Please try later.</string> <string name="error_063">Invalid broadband account.</string> <string name="error_064">Operation failed. Please try later.</string> <string name="error_066">Invalid account type.</string> <string name="error_067">The password cannot be empty.</string> <string name="error_068">The confirmation password cannot be empty.</string> <string name="error_069">The account cannot be empty.</string> <string name="error_070">Incorrect PPPoE account.</string> <string name="error_072">The cloud account is empty.</string> <string name="error_073">Incorrect cloud account type.</string> <string name="error_075">The cloud account is registered.</string> <string name="error_076">The cloud account does not exist.</string> <string name="error_077">You have not bound any broadband account or gateway.</string> <string name="error_078">The MAC address of the device is not registered to the cloud platform. </string> <string name="error_081">The current binding relationship does not exist.</string> <string name="error_082">The user account does not exist.</string> <string name="error_087">Binding failed, No broadband account.</string> <string name="error_093">You have not bound any broadband account.</string> <string name="error_094">The number of gateways to be bound has reached the maximum. New gateways cannot be bound.</string> <string name="error_097">Broadband account verification is not currently available.</string> <string name="error_098">The device already exists.</string> <string name="error_099">The Wi-Fi SSID already exists.</string> <string name="error_100">The Wi-Fi SSID is empty.</string> <string name="error_101">The account is added.</string> <string name="error_103">The password will expire soon.</string> <string name="error_105">The user account is locked.</string> <string name="error_106">User login failed.</string> <string name="error_107">Exceeded the number limit of accounts that can be logged in at the same time.</string> <string name="error_108">Password complexity is invalid.</string> <string name="error_110">Incorrect mobile phone type.</string> <string name="error_111">The mobile phone version is empty.</string> <string name="error_112">Exceeded the password resetting limit in 24 hours.</string> <string name="error_113">Exceeded the number limit of security question attempts. The password resetting is locked.</string> <string name="error_114">Incorrect answer to the security question.</string> <string name="error_115">Invalid parameter for the security question.</string> <string name="error_116">Incorrect old password.</string> <string name="error_117">No plug-in version.</string> <string name="error_118">Incorrect password.</string> <string name="error_121">Invalid order number.</string> <string name="error_122">WO cloud account has been registered.</string> <string name="error_123">WO cloud account does not exist.</string> <string name="error_124">WO cloud client authentication failed.</string> <string name="error_133">Failed to join.</string> <string name="error_139">Only administrators have this permission.</string> <string name="error_144">The log file size exceeds 5 MB and cannot be uploaded.</string> <string name="error_145">Plug-in already exists.</string> <string name="error_146">Plug-in version already exists.</string> <string name="error_150">The log switch has been enabled.</string> <string name="error_151">The log switch has been disabled.</string> <string name="error_152">Failed to query third-party authentication information.</string> <string name="error_153">Failed to forward plug-in third-party authentication information.</string> <string name="error_154">Duplicate room name.</string> <string name="error_155">The message template cannot be left empty.</string> <string name="error_156">The message template does not exist.</string> <string name="error_157">The mapping SMS template does not exist.</string> <string name="error_158">The SMS gateway is unavailable.</string> <string name="error_159">The plug-in service name is left empty or does not exist.</string> <string name="error_160">The plug-in service code is left empty or does not exist.</string> <string name="error_161">The plug-in random code is left blank or does not exist.</string> <string name="error_162">The mobile number cannot be left empty.</string> <string name="error_163">Failed to connect to the SMS gateway.</string> <string name="error_164">Failed to bind the SMS gateway.</string> <string name="error_165">Failed to send the SMS message.</string> <string name="error_166">SMS sending timed out.</string> <string name="error_171">The email address for receiving an authentication code is not the email address of the administrator.</string> <string name="error_172">The format of the message notification switch is incorrect.</string> <string name="error_173">The user password of the storage service fails the verification.</string> <string name="error_174">Status of the gateway to which the user is bound is invalid.</string> <string name="error_175">The email server is not configured.</string> <string name="error_176">Failed to send the email.</string> <string name="error_184">Sender authentication on the email server failed.</string> <string name="error_185">Incorrect email address.</string> <string name="error_186">Operation failed. Please try later.</string> <string name="error_187">Operation failed. Please try later.</string> <string name="error_189">You do not have the permission to access the gateway.</string> <string name="error_192">This type of message is not currently supported by the SMS gateway.</string> <string name="error_193">Sessiontimeout must be specified if the speed-up interface oper_type is set to 0.</string> <string name="error_196">Image size too large.</string> <string name="error_197">Incorrect image format.</string> <string name="error_198">The plug-in software version is not available.</string> <string name="error_199">Mandatory parameter symbolicName not found.</string> <string name="error_200">The plug-in record is empty.</string> <string name="error_204">BSS is not configured.</string> <string name="error_205">Failed to register the cloud account.</string> <string name="error_209">Mandatory parameter #{field} is not carried or is left empty.</string> <string name="error_210">Invalid request format.</string> <string name="error_211">The password has expired.</string> <string name="error_212">The user is blocked.</string> <string name="error_213">The MAC address is not bound.</string> <string name="error_215">You have not purchased such type of device.</string> <string name="error_216">Failed to identify the device type.</string> <string name="error_217">The number of devices of this type exceeds the maximum allowed by the package.</string> <string name="error_218">The package has not been activated.</string> <string name="error_222">Cloud storage has not been configured on the web page.</string> <string name="error_226">The account is not bound to a mobile number.</string> <string name="error_227">The account is not bound to an email address.</string> <string name="error_228">The cloud storage parameters cannot be left empty.</string> <string name="error_230">Failed to create the temporary Amazon Cloud certificate.</string> <string name="error_231">The verification code has expired.</string> <string name="error_232">No profile image has been uploaded for the user.</string> <string name="error_233">The application has not been purchased.</string> <string name="error_234">Incorrect cloud storage configuration.</string> <string name="error_236">Failed to obtain the cloud token.</string> <string name="error_237">Non-current administrator to create sub-accounts</string> <string name="error_244">The mobile number cannot be used for login.</string> <string name="error_245">The email address cannot be used for login.</string> <string name="error_246">The account cannot be modified repeatedly.</string> <string name="error_248">The plug-in is the latest version.</string> <string name="error_249">The login has expired.</string> <string name="error_250">The plug-in is the latest version.</string> <string name="error_251">Users with no service provisioned cannot bind a gateway.</string> <string name="error_252">The mobile number bound to the new administrator does not match the number segment specified by the carrier.</string> <string name="error_253">The mobile phone number bound to the new administrator is not used.</string> <string name="error_254">The mobile phone number bound to the new administrator has been used.</string> <string name="error_256">Your account has been disabled.</string> <string name="error_1018">Your password has been reset, please set a new password on the cloud platform</string> <string name="error_30000001">Operation failed. Please try later.</string> <string name="error_30000101">The account already exists.</string> <string name="error_30000102">The account does not exist.</string> <string name="error_30000103">The new account already exists.</string> <string name="error_30000104">The mobile number already exists.</string> <string name="error_30000105">The email address already exists.</string> <string name="error_30000106">The package does not exist.</string> <string name="error_30000107">Product ID{#{field}} does not exist.</string> <string name="error_30000108">Incorrect email address format.</string> <string name="error_30000109">The password does not meet the complexity requirements. Enter a correct one.</string> <string name="error_30000110">The account is not an administrator account.</string> <string name="error_30000111">No gateway has been bound for the account.</string> <string name="error_30000112">Multiple gateways have been bound for the account.</string> <string name="error_30000113">The gateway bound to this account has been enabled for remote management.</string> <string name="error_30000114">The gateway bound to this account has suspended remote management</string> <string name="error_30000115">The package is not specified.</string> <string name="error_30000116">Failed to delete the storage service file.</string> <string name="error_30000121">Unknown northbound bundle operation.</string> <string name="error_30000122">The plug-in software version is not found.</string> <string name="error_30000123">The plug-in software version already exists.</string> <string name="error_30000124">Mandatory parameter symbolicName is not specified.</string> <string name="error_30000125">The plug-in record is empty.</string> <string name="error_30000126">The plug-in has been bound to an app.</string> <string name="error_30000127">The plug-in does not exist.</string> <string name="error_30000128">The format of the mobile number is incorrect.</string> <string name="error_30000129">A new account cannot be the same as the old account.</string> <string name="error_30000130">The password must be different from previous passwords.</string> <string name="error__1004">The service package is not available for use.</string> <string name="error__1008">The entered broadband account is inconsistent with the one used for dial-up access.</string> <string name="error__1011">The user is offline.</string> <string name="error__1012">Subscribed services have expired.</string> <string name="error__1014">The IP address is outside the IP address range that has access to smart speed-up.</string> <string name="error__1015">The remaining quota is zero.</string> <string name="error_2002">The room does not exist.</string> <string name="error_2003">The device SN does not exist.</string> <string name="error_2004">The device is already added.</string> <string name="error_2005">No such device service is purchased.</string> <string name="error_2006">The package is not activated.</string> <string name="error_2007">The number of devices exceeds the limit of package.</string> <string name="error_2008">The device name already exists.</string> <string name="error_10100502">The service is invalid.</string> <string name="error_10100503">The service has ceased.</string> <string name="error_10100505">The service package does not exist.</string> <string name="error_10100508">BOD services do not support accumulation.</string> <string name="error_10100509">No basic-bandwidth information is available to calculate the amount of additional BOD bandwidth required.</string> <string name="error_10100601">The service is not subscribed.</string> <string name="error_10100602">The service is in used.</string> <string name="error_10100604">The service is not in use and the acceleration does not need to be stopped.</string> <string name="error_999">Operation failed. Please try later.</string> <string name="error_999108">Operation failed. Please try later.</string> <string name="error_999100">Service cannot parse XML-request and detect necessary fields</string> <string name="error_999101">Account for requested login or contract number is not found (for methods like balance checking)</string> <string name="error_999102">The contract attachment of the requested number is not found.</string> <string name="error_999103">Service with the requested number is not found</string> <string name="error_999104">Wrong phone number format</string> <string name="error_999105">Wrong email format</string> <string name="error_999106">Password doesn\'t meet the requirements (too short, etc)</string> <string name="error_999107">Error of internal account identification</string> <string name="error_999200">Method is not supported or not currently available</string> <string name="error_999202">BSS returns an error indicating that changing the mobile phone number failed.</string> <string name="error_999203">BSS returns an error indicating that changing the email address failed.</string> <string name="error_999300">Error during internal request processing in billing system (it will be returned XML-structure with details of the error)</string> <string name="error_network_err">Connection timed out. Check your network connection.</string> <string name="error_40000002">The length exceeds the maximum limit.</string> <string name="error_40000005">The parameter value exceeds the maximum value.</string> <string name="error_40000006">The parameter value is less than the minimum value.</string> <string name="error_80010001">The scene name already exists.</string> <string name="error_80010002">The scene name is empty.</string> <string name="error_80010003">The scene contains non-existing or deleted devices.</string> <string name="error_80010004">The scene name does not exist.</string> <string name="error_80000001">The plug-in name is empty.</string> <string name="error_80000002">The data flag is empty.</string> <string name="error_80010005">The action of the device is empty.</string> <string name="error_80010006">The device type does not exist.</string> <string name="error_80011001">The app name does not exist.</string> <string name="error_80011002">The operation name is empty.</string> <string name="error_80011003">The service name does not exist.</string> <string name="error_80012001">The camera password is incorrect or locked.</string> <string name="error_80013001">More rooms are created than allowed.</string> <string name="error_80010007">Incorrect time format in the scheduled scene.</string> <string name="error_80010008">The action name is empty.</string> <string name="error_80010009">Name of trigger condition is empty.</string> <string name="error_1013">The MAC address of your gateway does not exist on the server.</string> <string name="logo_homeGatewayService.token.invalid">Your login has expired.</string> <string name="error_1014">The number of verification codes sent in your account has reached the maximum. Please try again tomorrow.</string> <string name="error_0x02163dc3">The number of same characters in a row in the password has exceeded the maximum.</string> <string name="error_0x02163dcc">Failed to input the correct old password.</string> <string name="error_0x02163dc1">The password does not meet requirements.</string> <string name="error_0x02163dc2">The length of the password does not meet requirements.</string> <string name="error_0x021639b8">The new password must contain at least two characters that are not used in the old password.</string> <string name="error_0x02163dc4">The password does not comply with the repetition policy.</string> <string name="error_0x02163dc6">The operation does not comply with the minimum modification time interval.</string> <string name="error_0035014004">Password entered incorrectly too many times, please wait %1$s minutes and try again.</string> <string name="error_276">The mobile number has been registered with another broadband service provider and cannot be invited.</string> <string name="error_across_tenant">The mobile number has been registered with another broadband service provider, so you cannot invite it.</string> <string name="error__11">Operation failed. Please try later.</string> <string name="error__12">Operation failed. Please try later.</string> <string name="error_HomeGatewayService_parameter_invalid">Incorrect request parameter.</string> <string name="error_HomeGatewayService_cmdtype_invalid">The current platform version does not support this function.</string> <string name="error_HomeGatewayService_service_invalid">Server error.</string> <string name="error_HomeGatewayService_homegateway_no_permission">You do not have permission to manage the gateway.</string> <string name="error_281">Failed to send the SMS message. Please contact your broadband service provider.</string> <string name="error_282">The server fails to send an SMS message because the mobile number is invalid.</string> <string name="error_283">The server fails to send an SMS message because the mobile number is invalid.</string> <string name="error_284">The server is busy sending SMS messages. Please try again later.</string> <string name="error_285">The server is busy sending SMS messages. Please try again later.</string> <string name="error_286">The server fails to send the SMS message because the content is invalid.</string> <string name="error_287">The server fails to send an SMS message because the number is in the blacklist.</string> <string name="error_288">The SMS message sent by the server contains sensitive words. Change your gateway remarks and try again.</string> <string name="error_0">Operation successful.</string> <string name="error_7">The gateway is busy and cannot process the current request. Try again later.</string> <string name="error__1">Operation failed. Please try later.</string> <string name="error__2">Network request timed out.</string> <string name="error__36">The Wi-Fi service has been disabled.</string> <string name="error__100">Failed to assign transit server port. Try again</string> <string name="error__101">Failed to connect to the transit server. Check if the server is online.</string> <string name="error__105">Failed to obtain the video service address of the camera</string> <string name="error__108">User authentication failed</string> <string name="error__202">When MLO is enabled, the authentication mode must be WPA2, WPA3, or WPA2/WPA3.</string> <string name="error_001">Duplicate username.</string> <string name="error_002">Passwords don’t match.</string> <string name="error_003">Incorrect username or password.</string> <string name="error_005">The length of the password does not meet requirements.</string> <string name="error_007">The username cannot be empty.</string> <string name="error_008">Duplicate nickname.</string> <string name="error_013">Incorrect username or password.</string> <string name="error_014">Exceeded the maximum number of terminals bound to the current account.</string> <string name="error_015">Exceeded the maximum number of accounts bound to this terminal.</string> <string name="error_016">No smart ONT has been bound</string> <string name="error_020">The gateway is offline.</string> <string name="error_021">You do not have the permission to access the gateway.</string> <string name="error_022">The gateway is not registered.</string> <string name="error_023">The username does not exist.</string> <string name="error_029">No terminal is bound to this account.</string> <string name="error_039">The mobile number has not been bound to an account.</string> <string name="error_041">Failed to modify the password: The old password is entered incorrectly.</string> <string name="error_043">The gateway connection timed out. Try again later or check whether the gateway network is connected.</string> <string name="error_045">Operation failed. Please try later.</string> <string name="error_046">Operation failed. Please try later.</string> <string name="error_047">Failed to obtain the device control list.</string> <string name="error_049">Exceeded the maximum number of controllable devices.</string> <string name="error_052">The gateway is not registered.</string> <string name="error_053">Device control is not supported.</string> <string name="error_054">Operation failed. Please try later.</string> <string name="error_055">Unknown error occurred on the device control template.</string> <string name="error_065">Problem description cannot be empty.</string> <string name="error_071">Not a smart gateway.</string> <string name="error_079">Operation failed: the gateway has been unbound.</string> <string name="error_080">Operation failed: the current account has not joined.</string> <string name="error_083">Operation failed. Please try later.</string> <string name="error_084">A non-invite user cannot modify the remarks.</string> <string name="error_085">Unbinding failed. Please try again later.</string> <string name="error_086">Devices exist in the room.</string> <string name="error_088">This app does not support non-smart gateways.</string> <string name="error_089">Binding failed. Please try again later.</string> <string name="error_090">Binding failed. Please try again later.</string> <string name="error_091">Binding failed. Please try again later.</string> <string name="error_092">The number of invited users has exceeded the upper limit.</string> <string name="error_095">Deletion failed. The last user cannot be deleted.</string> <string name="error_096">The list of network users to be deleted is empty.</string> <string name="error_102">The new password cannot be the same as any previous password.</string> <string name="error_104">The password has expired.</string> <string name="error_109">The greeting message is empty.</string> <string name="error_119">The room name cannot be empty.</string> <string name="error_120">The room ID cannot be empty.</string> <string name="error_125">The username does not meet the complexity requirements. Enter a correct one.</string> <string name="error_126">The username cannot be empty.</string> <string name="error_127">The username does not meet the complexity requirements. Enter a correct one.</string> <string name="error_128">No mobile number is bound.</string> <string name="error_129">This mobile number is not a administrator account.</string> <string name="error_130">The mobile number must be a Bahraini number.</string> <string name="error_131">The mobile number has been bound.</string> <string name="error_132">No phone number is bound to the current account.</string> <string name="error_134">Administrators cannot leave.</string> <string name="error_135">The mobile number is not bound to any account.</string> <string name="error_136">The login has expired.</string> <string name="error_140">The device has been updated to the latest version.</string> <string name="error_141">No new version is available.</string> <string name="error_143">Incorrect log file format.</string> <string name="error_147">The gateway is being upgraded.</string> <string name="error_148">The phone number has already been registered once, please use another number or use this number to login.</string> <string name="error_149">Duplicate room name.</string> <string name="error_167">Operation failed. Please try later.</string> <string name="error_168">Starting the plug-in…</string> <string name="error_169">Stopping the plug-in…</string> <string name="error_170">Uninstalling the plug-in…</string> <string name="error_188">The gateway does not exist.</string> <string name="error_190">You do not have access to this gateway.</string> <string name="error_191">The message push type is empty or of an incorrect format.</string> <string name="error_194">Operation failed. Please try later.</string> <string name="error_195">You cannot invite other network members to join.</string> <string name="error_LHConsumerService_login_accountRoleMismatch">Members from other enterprises are not allowed.</string> <string name="error_LHConsumerService_bindGroup_exceedMaxBindGroupNum">Members from other enterprises are not allowed.</string> <string name="error_201">Failed to check the remaining balance.</string> <string name="error_202">Failed to change the mobile number.</string> <string name="error_203">Failed to change the email address.</string> <string name="error_214">Incorrect addedDeviceList format.</string> <string name="error_219">The password cannot be the same as the username or the username in reverse.</string> <string name="error_220">You do not have the administrative permission.</string> <string name="error_221">Failed to uninstall all the plug-ins of the home gateway.</string> <string name="error_224">The new gateway is not registered.</string> <string name="error_225">The new home gateway has been bound.</string> <string name="error_238">Your account has not been bound with a mobile number or email address. The password cannot be retrieved through self service. You are advised to contact your administrator to retrieve the password.</string> <string name="error_239">The mobile number is bound to multiple accounts.</string> <string name="error_240">The email address is bound to multiple accounts.</string> <string name="error_247">Anonymous binding information cannot be queried by using a mobile number or an email address.</string> <string name="error_255">The account has been bound to a gateway, and cannot be bound to another one.</string> <string name="error_272">Incorrect username or password.</string> <string name="error_1002">The interval between requests for sending verification codes is too short.</string> <string name="error_30000117">The home gateway MAC address does not exist.</string> <string name="error_30000118">The home gateway is offline.</string> <string name="error_30000119">The home gateway plug-in does not exist.</string> <string name="error_30000120">The plug-in is not installed or not upgraded on the home gateway.</string> <string name="error__1013">The MAC address (XXX) of your gateway does not exist on the server.</string> <string name="error_2001">The input parameter is empty.</string> <string name="error_40000001">The parameter contains unsupported special characters.</string> <string name="error_40000003">The length is less than the minimum limit.</string> <string name="error_40000004">The parameter is not a numeric type.</string> <string name="error_40000007">Invalid IP address.</string> <string name="net_conn_failed">Connection failed.</string> <string name="error__3">Connection failed.</string> <string name="error__4">The gateway is busy and cannot process the current request. Try again later.</string> <string name="error__5">Operation failed. Please try later.</string> <string name="error__7">Operation failed. Please try later.</string> <string name="error__8">Not supported by the gateway.</string> <string name="error__9">Operation failed. Please try later.</string> <string name="error__10">Your login has expired. Please log in again.</string> <string name="error_280">Failed to send the SMS message. Please try again later.</string> <string name="error_300">The current server version does not support user name registration.</string> <string name="error__102">Camera offline or camera connection failed. Check if the camera is powered on.</string> <string name="error__104">Camera video service address illegal, please report impaired</string> <string name="error__106">Gateway cannot connect to the transit server. Check if the server is online.</string> <string name="error__200">Reached the upper limit.</string> <string name="error__201">When MLO is enabled, the working mode must be 802.11be.</string> <string name="error__203">Saving Wi-Fi settings. Please wait.</string> <string name="error__204">Incorrect request parameter.</string> <string name="error__205">The Wi-Fi frequency band is not enabled. Enable it first.</string> <string name="error__301">Fails to play the real-time video of the camera. Failed to connect to the gateway locally.</string> <string name="error__330">Application control is not enabled. Please enable it first.</string> <string name="error__331">The number of application control policies has reached the upper limit.</string> <string name="error__332">The app control rule does not exist.</string> <string name="error__622">The rate limit periods cannot overlap with each other.</string> <string name="error_028">Your account has been used for login on another device. If this was done without your knowledge, your account and password may have been compromised. Choose Settings > Account And Security to change your account password.</string> <string name="error_2009">Failed to query the package status.</string> <string name="error__99999">Operation failed. Please try later.</string> <string name="error_1017">The MAC address cannot be empty.</string> <string name="error_licence_expire">Licence expired, please contact service provider.</string> <string name="LHConsumerService.bindLocalAccount.hasFamily">The account is already in a family.</string> <string name="LHConsumerService.bindLocalAccount.bound">Already bound to another account.</string> <string name="LHConsumerService.weakvalue.error">The password is too simple.</string> <string name="error_LHConsumerService_feedback_daylimit">The number of problems you reported has reached the upper limit. Try again 24 hours later.</string> <string name="error_306">Failed to send the verification code.The possible cause is that the mobile number format is incorrect or the mobile number has been bound.</string> <string name="error_307">Failed to send the verification code.The possible cause is that the email address format is incorrect or the email address has been bound.</string> <string name="error_308">Failed to send the verification code.The possible cause is that the mobile number format is incorrect or the mobile number is not bound.</string> <string name="error_309">Failed to send the verification code.The possible cause is that the email address format is incorrect or the email address is not bound.</string> <string name="error_310">The client IP address is locked,please try again later.</string> <string name="error_311">The current version does not support multi-factor authentication. Contact the administrator to disable multi-factor authentication.</string> <string name="error__340">The portal function has been enabled. The speed limit cannot be configured. To set the rate limit, disable Portal authentication on the web management page of the gateway.</string> <string name="error_AppSdk_notInitialized">Failed to initialize the app. Please log in again.</string> <string name="error_log_collect_offline">Device is offline</string> <string name="error_log_collect_conflict">Another collection task of the device is in progress.</string> <string name="error_log_collect_failed">Log collection failed</string> <string name="LHConsumerService.domainMigration.notSupportBinding">The server has been switched. Please switch to the corresponding region and register again.</string> <string name="error__41">Failed to set the 5G Wi-Fi because it has been locked. Contact your carrier to enable it first.</string> <string name="error__14">The same Wi-Fi SSID already exists in the current frequency band.</string> <string name="BindGateway_101">You have joined a family. Please refresh the home page and view it.</string> <string name="error_third_platform_user">Third-party users exist, unbinding failed.</string> </resources>

package com.example.vcam; import android.Manifest; import android.app.Application; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.SurfaceTexture; //import android.hardware.Camera; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CaptureFailure; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.params.InputConfiguration; import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.params.SessionConfiguration; import android.media.MediaPlayer; import android.os.Build; import android.os.Environment; import android.os.Handler; import android.view.Surface; import android.view.SurfaceHolder; import android.view.View; import android.widget.Toast; import com.example.vcam.event.EventProxyHandler; import com.example.vcam.event.SomeEvent; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.concurrent.Executor; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class HookMain implements IXposedHookLoadPackage { public static Surface mSurface; public static SurfaceTexture mSurfacetexture; public static MediaPlayer mMediaPlayer; public static SurfaceTexture fake_SurfaceTexture; //public static Camera origin_preview_camera; //public static Camera camera_onPreviewFrame; //public static Camera start_preview_camera; public static volatile byte[] data_buffer = {0}; public static byte[] input; public static int mhight; public static int mwidth; public static boolean is_someone_playing; public static boolean is_hooked; public static VideoToFrames hw_decode_obj; public static VideoToFrames c2_hw_decode_obj; public static VideoToFrames c2_hw_decode_obj_1; public static SurfaceTexture c1_fake_texture; public static Surface c1_fake_surface; public static SurfaceHolder ori_holder; public static MediaPlayer mplayer1; //public static Camera mcamera1; public int imageReaderFormat = 0; public static boolean is_first_hook_build = true; public static int onemhight; public static int onemwidth; public static Class camera_callback_calss; public static String video_path = "/storage/emulated/0/DCIM/Camera1/"; public static Surface c2_preview_Surfcae; public static Surface c2_preview_Surfcae_1; public static Surface c2_reader_Surfcae; public static Surface c2_reader_Surfcae_1; public static MediaPlayer c2_player; public static MediaPlayer c2_player_1; public static Surface c2_virtual_surface; public static SurfaceTexture c2_virtual_surfaceTexture; public boolean need_recreate; public static CameraDevice.StateCallback c2_state_cb; public static CaptureRequest.Builder c2_builder; public static SessionConfiguration fake_sessionConfiguration; public static SessionConfiguration sessionConfiguration; public static OutputConfiguration outputConfiguration; public boolean need_to_show_toast = true; private static Context appContext; public int c2_ori_width = 1280; public int c2_ori_height = 720; public static Class c2_state_callback; public Context toast_content; private static ClassLoader hostClassLoader; // 视频源管理器 //public static VideoSourceManager videoSourceManager = new VideoSourceManager(); VideoSourceManager manager = VideoSourceManager.getInstance(); public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Exception { // 初始化视频源管理器 if (manager == null) { manager = new VideoSourceManager(); } // 添加默认视频源 String defaultVideo = video_path + "virtual.mp4"; manager.addVideoSource("default", defaultVideo); manager.setCurrentSource("default"); if (lpparam.packageName.equals("com.example.vcam")){ XposedBridge.log("【VCAM】event2 " + lpparam.packageName); hostClassLoader = lpparam.classLoader; Class<?> mainActivityClass = hostClassLoader.loadClass( "com.example.vcam.MainActivity" ); Class<?> iEventInterface = hostClassLoader.loadClass( "com.example.vcam.IEvent" ); XposedHelpers.findAndHookMethod(mainActivityClass,"onEvent", iEventInterface,new XC_MethodHook(){ @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { //XposedBridge.log("【VCAM】event2 onEvent" ); Object event = param.args[0]; // EventProxyHandler.handleEvent( // event, // event.getClass() // 使用实际运行时类 // ); Method getMessage = iEventInterface.getMethod("getMessage"); String MessageStr = (String) getMessage.invoke(event); Method getBeiCan1 = iEventInterface.getMethod("getBeiCan1"); String BeiCan1Str = (String) getBeiCan1.invoke(event); XposedBridge.log("【VCAM】event " + MessageStr); XposedBridge.log("【VCAM】eventpath " + BeiCan1Str); if (MessageStr == "qiehuan1") { String sourceName = "source_virtual21"; // 添加新视频源(如果不存在) if (!manager.videoSources.containsKey(sourceName)) { manager.addVideoSource(sourceName, BeiCan1Str); } // 切换到新视频源 manager.switchToSource(sourceName); // 通知相机重启 // manager.onCameraRestart(); // 强制重启相机 // forceRestartCamera(lpparam); process_camera2_play(); } } }); } XposedHelpers.findAndHookMethod("android.hardware.camera2.CameraManager", lpparam.classLoader, "openCamera", String.class, CameraDevice.StateCallback.class, Handler.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { if (param.args[1] == null) { return; } if (param.args[1].equals(c2_state_cb)) { return; } c2_state_cb = (CameraDevice.StateCallback) param.args[1]; c2_state_callback = c2_state_cb.getClass(); //param.args[1].getClass(); File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "disable.jpg"); if (control_file.exists()) { return; } File file = new File(video_path + "virtual.mp4"); File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "no_toast.jpg"); need_to_show_toast = !toast_control.exists(); if (!file.exists()) { if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n" + lpparam.packageName + "当前路径1:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { XposedBridge.log("【VCAM】[toast]" + ee.toString()); } } return; } XposedBridge.log("【VCAM】1位参数初始化相机,类:" + c2_state_callback.getName().toString()); is_first_hook_build = true; process_camera2_init(c2_state_callback); if(c2_state_callback ==null){ XposedBridge.log("【VCAM】c2_state_callback33 为null" ); } } }); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { XposedHelpers.findAndHookMethod("android.hardware.camera2.CameraManager", lpparam.classLoader, "openCamera", String.class, Executor.class, CameraDevice.StateCallback.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("【VCAM】2位参数初始化相机,类:" + c2_state_callback.toString()); if (param.args[2] == null) { return; } if (param.args[2].equals(c2_state_cb)) { return; } c2_state_cb = (CameraDevice.StateCallback) param.args[2]; File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "disable.jpg"); if (control_file.exists()) { return; } File file = new File(video_path + "virtual.mp4"); File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "no_toast.jpg"); need_to_show_toast = !toast_control.exists(); if (!file.exists()) { if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n" + lpparam.packageName + "当前路径2:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { XposedBridge.log("【VCAM】[toast]" + ee.toString()); } } return; } c2_state_callback = param.args[2].getClass(); XposedBridge.log("【VCAM】2位参数初始化相机,类:" + c2_state_callback.toString()); is_first_hook_build = true; process_camera2_init(c2_state_callback); } }); } // XposedHelpers.findAndHookMethod("android.media.MediaRecorder", lpparam.classLoader, "setCamera", Camera.class, new XC_MethodHook() { // @Override // protected void beforeHookedMethod(MethodHookParam param) throws Throwable { // super.beforeHookedMethod(param); // File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "no_toast.jpg"); // need_to_show_toast = !toast_control.exists(); // XposedBridge.log("【VCAM】[record]" + lpparam.packageName); // if (toast_content != null && need_to_show_toast) { // try { // Toast.makeText(toast_content, "应用:" + lpparam.appInfo.name + "(" + lpparam.packageName + ")" + "触发了录像,但目前无法拦截", Toast.LENGTH_SHORT).show(); // }catch (Exception ee){ // XposedBridge.log("【VCAM】[toast]" + Arrays.toString(ee.getStackTrace())); // } // } // } // }); XposedHelpers.findAndHookMethod("android.app.Instrumentation", lpparam.classLoader, "callApplicationOnCreate", Application.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); if (param.args[0] instanceof Application) { try { toast_content = ((Application) param.args[0]).getApplicationContext(); } catch (Exception ee) { XposedBridge.log("【VCAM】" + ee.toString()); } File force_private = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM/Camera1/private_dir.jpg"); if (toast_content != null) {//后半段用于强制私有目录 int auth_statue = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { try { auth_statue += (toast_content.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) + 1); } catch (Exception ee) { XposedBridge.log("【VCAM】[permission-check]" + ee.toString()); } try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { auth_statue += (toast_content.checkSelfPermission(Manifest.permission.MANAGE_EXTERNAL_STORAGE) + 1); } } catch (Exception ee) { XposedBridge.log("【VCAM】[permission-check]" + ee.toString()); } }else { if (toast_content.checkCallingPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED ){ auth_statue = 2; } } //权限判断完毕 if (auth_statue < 1 || force_private.exists()) { File shown_file = new File(toast_content.getExternalFilesDir(null).getAbsolutePath() + "/Camera1/"); if ((!shown_file.isDirectory()) && shown_file.exists()) { shown_file.delete(); } if (!shown_file.exists()) { shown_file.mkdir(); } shown_file = new File(toast_content.getExternalFilesDir(null).getAbsolutePath() + "/Camera1/" + "has_shown"); File toast_force_file = new File(Environment.getExternalStorageDirectory().getPath()+ "/DCIM/Camera1/force_show.jpg"); if ((!lpparam.packageName.equals(BuildConfig.APPLICATION_ID)) && ((!shown_file.exists()) || toast_force_file.exists())) { try { Toast.makeText(toast_content, lpparam.packageName+"未授予读取本地目录权限,请检查权限\nCamera1目前重定向为 " + toast_content.getExternalFilesDir(null).getAbsolutePath() + "/Camera1/", Toast.LENGTH_SHORT).show(); FileOutputStream fos = new FileOutputStream(toast_content.getExternalFilesDir(null).getAbsolutePath() + "/Camera1/" + "has_shown"); String info = "shown"; fos.write(info.getBytes()); fos.flush(); fos.close(); } catch (Exception e) { XposedBridge.log("【VCAM】[switch-dir]" + e.toString()); } } video_path = toast_content.getExternalFilesDir(null).getAbsolutePath() + "/Camera1/"; }else { video_path = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/"; } } else { video_path = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/"; File uni_DCIM_path = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/"); if (uni_DCIM_path.canWrite()) { File uni_Camera1_path = new File(video_path); if (!uni_Camera1_path.exists()) { uni_Camera1_path.mkdir(); } } } } } }); XposedHelpers.findAndHookMethod("android.hardware.camera2.CaptureRequest.Builder", lpparam.classLoader, "addTarget", Surface.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { if (param.args[0] == null) { return; } if (param.thisObject == null) { return; } File file = new File(video_path + "virtual.mp4"); File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "no_toast.jpg"); need_to_show_toast = !toast_control.exists(); if (!file.exists()) { if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n" + lpparam.packageName + "当前路径3:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { XposedBridge.log("【VCAM】[toast]" + ee.toString()); } } return; } if (param.args[0].equals(c2_virtual_surface)) { return; } File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "disable.jpg"); if (control_file.exists()) { return; } String surfaceInfo = param.args[0].toString(); if (surfaceInfo.contains("Surface(name=null)")) { if (c2_reader_Surfcae == null) { c2_reader_Surfcae = (Surface) param.args[0]; } else { if ((!c2_reader_Surfcae.equals(param.args[0])) && c2_reader_Surfcae_1 == null) { c2_reader_Surfcae_1 = (Surface) param.args[0]; } } } else { if (c2_preview_Surfcae == null) { c2_preview_Surfcae = (Surface) param.args[0]; } else { if ((!c2_preview_Surfcae.equals(param.args[0])) && c2_preview_Surfcae_1 == null) { c2_preview_Surfcae_1 = (Surface) param.args[0]; } } } XposedBridge.log("【VCAM】添加目标:" + param.args[0].toString()); if(c2_state_callback ==null){ XposedBridge.log("【VCAM】c2_state_callback4 为null" ); } param.args[0] = c2_virtual_surface; } }); XposedHelpers.findAndHookMethod("android.hardware.camera2.CaptureRequest.Builder", lpparam.classLoader, "addTarget", Surface.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { Surface surface = (Surface) param.args[0]; // VideoSourceManager.getInstance().prepareForSurface(surface); } }); XposedHelpers.findAndHookMethod("android.hardware.camera2.CaptureRequest.Builder", lpparam.classLoader, "removeTarget", Surface.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { if (param.args[0] == null) { return; } if (param.thisObject == null) { return; } File file = new File(video_path + "virtual.mp4"); File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "no_toast.jpg"); need_to_show_toast = !toast_control.exists(); if (!file.exists()) { if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n" + lpparam.packageName + "当前路径4:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { XposedBridge.log("【VCAM】[toast]" + ee.toString()); } } return; } File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "disable.jpg"); if (control_file.exists()) { return; } Surface rm_surf = (Surface) param.args[0]; if (rm_surf.equals(c2_preview_Surfcae)) { c2_preview_Surfcae = null; } if (rm_surf.equals(c2_preview_Surfcae_1)) { c2_preview_Surfcae_1 = null; } if (rm_surf.equals(c2_reader_Surfcae_1)) { c2_reader_Surfcae_1 = null; } if (rm_surf.equals(c2_reader_Surfcae)) { c2_reader_Surfcae = null; } XposedBridge.log("【VCAM】移除目标:" + param.args[0].toString()); } }); XposedHelpers.findAndHookMethod("android.hardware.camera2.CaptureRequest.Builder", lpparam.classLoader, "build", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { if (param.thisObject == null) { return; } if (param.thisObject.equals(c2_builder)) { return; } c2_builder = (CaptureRequest.Builder) param.thisObject; File file = new File(video_path + "virtual.mp4"); File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "no_toast.jpg"); need_to_show_toast = !toast_control.exists(); if (!file.exists() && need_to_show_toast) { if (toast_content != null) { try { Toast.makeText(toast_content, "不存在替换视频\n" + lpparam.packageName + "当前路径5:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { XposedBridge.log("【VCAM】[toast]" + ee.toString()); } } return; } File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "disable.jpg"); if (control_file.exists()) { return; } XposedBridge.log("【VCAM】开始build请求"); if(c2_state_callback ==null){ XposedBridge.log("【VCAM】c2_state_callback5 为null" ); } process_camera2_play(); // XposedBridge.log("【VCAM】c2_state_callback6 为null" ); } }); XposedHelpers.findAndHookMethod("android.media.ImageReader", lpparam.classLoader, "newInstance", int.class, int.class, int.class, int.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { XposedBridge.log("【VCAM】应用创建了渲染器:宽:" + param.args[0] + " 高:" + param.args[1] + "格式" + param.args[2]); c2_ori_width = (int) param.args[0]; c2_ori_height = (int) param.args[1]; imageReaderFormat = (int) param.args[2]; File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "no_toast.jpg"); need_to_show_toast = !toast_control.exists(); if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "应用创建了渲染器:\n宽:" + param.args[0] + "\n高:" + param.args[1] + "\n一般只需要宽高比与视频相同", Toast.LENGTH_SHORT).show(); } catch (Exception e) { XposedBridge.log("【VCAM】[toast]" + e.toString()); } } } }); XposedHelpers.findAndHookMethod("android.hardware.camera2.CameraCaptureSession.CaptureCallback", lpparam.classLoader, "onCaptureFailed", CameraCaptureSession.class, CaptureRequest.class, CaptureFailure.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { XposedBridge.log("【VCAM】onCaptureFailed" + "原因:" + ((CaptureFailure) param.args[2]).getReason()); } }); } private void process_camera2_play() { if (c2_reader_Surfcae != null) { XposedBridge.log("【VCAM c2_reader_Surfcae 非空】" ); if (c2_hw_decode_obj != null) { c2_hw_decode_obj.stopDecode(); c2_hw_decode_obj = null; } c2_hw_decode_obj = new VideoToFrames(); try { if (imageReaderFormat == 256) { c2_hw_decode_obj.setSaveFrames("null", OutputImageFormat.JPEG); } else { c2_hw_decode_obj.setSaveFrames("null", OutputImageFormat.NV21); } c2_hw_decode_obj.set_surfcae(c2_reader_Surfcae); // c2_hw_decode_obj.decode(video_path + "virtual.mp4"); c2_hw_decode_obj.decode(VideoSourceManager.getInstance().getCurrentSource().path); } catch (Throwable throwable) { XposedBridge.log("【VCAM】" + throwable); } } if (c2_reader_Surfcae_1 != null) { XposedBridge.log("【VCAM c2_reader_Surfcae_1 非空】" ); if (c2_hw_decode_obj_1 != null) { c2_hw_decode_obj_1.stopDecode(); c2_hw_decode_obj_1 = null; } c2_hw_decode_obj_1 = new VideoToFrames(); try { if (imageReaderFormat == 256) { c2_hw_decode_obj_1.setSaveFrames("null", OutputImageFormat.JPEG); } else { c2_hw_decode_obj_1.setSaveFrames("null", OutputImageFormat.NV21); } c2_hw_decode_obj_1.set_surfcae(c2_reader_Surfcae_1); // c2_hw_decode_obj_1.decode(video_path + "virtual.mp4"); c2_hw_decode_obj_1.decode(VideoSourceManager.getInstance().getCurrentSource().path); } catch (Throwable throwable) { XposedBridge.log("【VCAM】" + throwable); } } if (c2_preview_Surfcae != null) { XposedBridge.log("【VCAM c2_preview_Surfcae 非空】" ); if (c2_player == null) { c2_player = new MediaPlayer(); } else { c2_player.release(); c2_player = new MediaPlayer(); } c2_player.setSurface(c2_preview_Surfcae); File sfile = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "no-silent.jpg"); if (!sfile.exists()) { c2_player.setVolume(0, 0); } c2_player.setLooping(true); try { c2_player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { public void onPrepared(MediaPlayer mp) { c2_player.start(); } }); // c2_player.setDataSource(video_path + "virtual.mp4"); c2_player.setDataSource(VideoSourceManager.getInstance().getCurrentSource().path); c2_player.prepare(); } catch (Exception e) { XposedBridge.log("【VCAM】[c2player][" + c2_preview_Surfcae.toString() + "]" + e); } } if (c2_preview_Surfcae_1 != null) { XposedBridge.log("【VCAM c2_preview_Surfcae_1 非空】" ); if (c2_player_1 == null) { c2_player_1 = new MediaPlayer(); } else { c2_player_1.release(); c2_player_1 = new MediaPlayer(); } c2_player_1.setSurface(c2_preview_Surfcae_1); File sfile = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "no-silent.jpg"); if (!sfile.exists()) { c2_player_1.setVolume(0, 0); } c2_player_1.setLooping(true); try { c2_player_1.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { public void onPrepared(MediaPlayer mp) { c2_player_1.start(); } }); //c2_player_1.setDataSource(video_path + "virtual.mp4"); c2_player_1.setDataSource(VideoSourceManager.getInstance().getCurrentSource().path); c2_player_1.prepare(); } catch (Exception e) { XposedBridge.log("【VCAM】[c2player1]" + "[ " + c2_preview_Surfcae_1.toString() + "]" + e); } } XposedBridge.log("【VCAM】Camera2处理过程完全执行"); } private Surface create_virtual_surface() { if (need_recreate) { if (c2_virtual_surfaceTexture != null) { c2_virtual_surfaceTexture.release(); c2_virtual_surfaceTexture = null; } if (c2_virtual_surface != null) { c2_virtual_surface.release(); c2_virtual_surface = null; } c2_virtual_surfaceTexture = new SurfaceTexture(15); c2_virtual_surface = new Surface(c2_virtual_surfaceTexture); need_recreate = false; } else { if (c2_virtual_surface == null) { need_recreate = true; c2_virtual_surface = create_virtual_surface(); } } XposedBridge.log("【VCAM】【重建垃圾场】" + c2_virtual_surface.toString()); return c2_virtual_surface; } // 在HookMain类中添加 private void recreateVirtualSurface() { if (c2_virtual_surface != null) { XposedBridge.log("【VCAM】重建虚拟Surface: 1"); c2_virtual_surface.release(); c2_virtual_surface = null; } if (c2_virtual_surfaceTexture != null) { XposedBridge.log("【VCAM】重建虚拟Surface: 2"); c2_virtual_surfaceTexture.release(); c2_virtual_surfaceTexture = null; } c2_virtual_surfaceTexture = new SurfaceTexture(15); c2_virtual_surface = new Surface(c2_virtual_surfaceTexture); need_recreate = false; XposedBridge.log("【VCAM】重建虚拟Surface: " + c2_virtual_surface.toString()); } // 释放Camera2相关资源 private void releaseCamera2Resources() { if (c2_player != null) { c2_player.stop(); c2_player.release(); c2_player = null; } if (c2_player_1 != null) { c2_player_1.stop(); c2_player_1.release(); c2_player_1 = null; } if (c2_hw_decode_obj != null) { c2_hw_decode_obj.stopDecode(); c2_hw_decode_obj = null; } if (c2_hw_decode_obj_1 != null) { c2_hw_decode_obj_1.stopDecode(); c2_hw_decode_obj_1 = null; } c2_preview_Surfcae = null; c2_preview_Surfcae_1 = null; c2_reader_Surfcae = null; c2_reader_Surfcae_1 = null; } private void process_camera2_init(Class hooked_class) { XposedBridge.log("【VCAM】重启跟踪1" ); if(hooked_class==null){ XposedBridge.log("【VCAM】hooked_class 为null" ); } //c2_state_callback if(c2_state_callback ==null){ XposedBridge.log("【VCAM】c2_state_callback1 为null" ); } XposedHelpers.findAndHookMethod(hooked_class, "onOpened", CameraDevice.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("【VCAM】重启跟踪2"); // 重建虚拟Surface recreateVirtualSurface(); XposedBridge.log("【VCAM】重启跟踪3"); // 释放旧资源 releaseCamera2Resources(); XposedBridge.log("【VCAM】重启跟踪4"); XposedBridge.log("【VCAM】相机设备已打开"); XposedBridge.log("【VCAM】打开相机C2"); final CameraDevice cameraDevice = (CameraDevice) param.args[0]; if(c2_state_callback ==null){ XposedBridge.log("【VCAM】c2_state_callback2 为null" ); } File file = new File(video_path + "virtual.mp4"); File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "no_toast.jpg"); need_to_show_toast = !toast_control.exists(); if (!file.exists()) { if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n" + toast_content.getPackageName() + "当前路径6:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { XposedBridge.log("【VCAM】[toast]" + ee.toString()); } } return; } XposedHelpers.findAndHookMethod(param.args[0].getClass(), "createCaptureSession", List.class, CameraCaptureSession.StateCallback.class, Handler.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam paramd) throws Throwable { // 替换为虚拟Surface paramd.args[0] = Arrays.asList(c2_virtual_surface); XposedBridge.log("【VCAM】配置CaptureSession使用虚拟Surface"); // if (paramd.args[0] != null) { // XposedBridge.log("【VCAM】createCaptureSession创捷捕获,原始:" + paramd.args[0].toString() + "虚拟:" + c2_virtual_surface.toString()); // paramd.args[0] = Arrays.asList(c2_virtual_surface); // if (paramd.args[1] != null) { // process_camera2Session_callback((CameraCaptureSession.StateCallback) paramd.args[1]); // } // } } }); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { XposedHelpers.findAndHookMethod(param.args[0].getClass(), "createCaptureSessionByOutputConfigurations", List.class, CameraCaptureSession.StateCallback.class, Handler.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); if (param.args[0] != null) { outputConfiguration = new OutputConfiguration(c2_virtual_surface); param.args[0] = Arrays.asList(outputConfiguration); XposedBridge.log("【VCAM】执行了createCaptureSessionByOutputConfigurations-144777"); if (param.args[1] != null) { process_camera2Session_callback((CameraCaptureSession.StateCallback) param.args[1]); } } } }); } XposedHelpers.findAndHookMethod(param.args[0].getClass(), "createConstrainedHighSpeedCaptureSession", List.class, CameraCaptureSession.StateCallback.class, Handler.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); if (param.args[0] != null) { param.args[0] = Arrays.asList(c2_virtual_surface); XposedBridge.log("【VCAM】执行了 createConstrainedHighSpeedCaptureSession -5484987"); if (param.args[1] != null) { process_camera2Session_callback((CameraCaptureSession.StateCallback) param.args[1]); } } } }); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { XposedHelpers.findAndHookMethod(param.args[0].getClass(), "createReprocessableCaptureSession", InputConfiguration.class, List.class, CameraCaptureSession.StateCallback.class, Handler.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); if (param.args[1] != null) { param.args[1] = Arrays.asList(c2_virtual_surface); XposedBridge.log("【VCAM】执行了 createReprocessableCaptureSession "); if (param.args[2] != null) { process_camera2Session_callback((CameraCaptureSession.StateCallback) param.args[2]); } } } }); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { XposedHelpers.findAndHookMethod(param.args[0].getClass(), "createReprocessableCaptureSessionByConfigurations", InputConfiguration.class, List.class, CameraCaptureSession.StateCallback.class, Handler.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); if (param.args[1] != null) { outputConfiguration = new OutputConfiguration(c2_virtual_surface); param.args[0] = Arrays.asList(outputConfiguration); XposedBridge.log("【VCAM】执行了 createReprocessableCaptureSessionByConfigurations"); if (param.args[2] != null) { process_camera2Session_callback((CameraCaptureSession.StateCallback) param.args[2]); } } } }); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { XposedHelpers.findAndHookMethod(param.args[0].getClass(), "createCaptureSession", SessionConfiguration.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); if (param.args[0] != null) { XposedBridge.log("【VCAM】执行了 createCaptureSession -5484987"); sessionConfiguration = (SessionConfiguration) param.args[0]; outputConfiguration = new OutputConfiguration(c2_virtual_surface); fake_sessionConfiguration = new SessionConfiguration(sessionConfiguration.getSessionType(), Arrays.asList(outputConfiguration), sessionConfiguration.getExecutor(), sessionConfiguration.getStateCallback()); param.args[0] = fake_sessionConfiguration; process_camera2Session_callback(sessionConfiguration.getStateCallback()); } } }); } } }); XposedHelpers.findAndHookMethod(hooked_class, "onError", CameraDevice.class, int.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("【VCAM】相机错误onerror:" + (int) param.args[1]); } }); XposedHelpers.findAndHookMethod(hooked_class, "onDisconnected", CameraDevice.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("【VCAM】相机断开onDisconnected :"); } }); } private void process_a_shot_jpeg(XC_MethodHook.MethodHookParam param, int index) { try { XposedBridge.log("【VCAM】第二个jpeg:" + param.args[index].toString()); } catch (Exception eee) { XposedBridge.log("【VCAM】" + eee); } Class callback = param.args[index].getClass(); } private void process_a_shot_YUV(XC_MethodHook.MethodHookParam param) { try { XposedBridge.log("【VCAM】发现拍照YUV:" + param.args[1].toString()); } catch (Exception eee) { XposedBridge.log("【VCAM】" + eee); } Class callback = param.args[1].getClass(); } private void process_callback(XC_MethodHook.MethodHookParam param) { Class preview_cb_class = param.args[0].getClass(); int need_stop = 0; File control_file = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "disable.jpg"); if (control_file.exists()) { need_stop = 1; } File file = new File(video_path + "virtual.mp4"); File toast_control = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera1/" + "no_toast.jpg"); need_to_show_toast = !toast_control.exists(); if (!file.exists()) { if (toast_content != null && need_to_show_toast) { try { Toast.makeText(toast_content, "不存在替换视频\n" + toast_content.getPackageName() + "当前路径7:" + video_path, Toast.LENGTH_SHORT).show(); } catch (Exception ee) { XposedBridge.log("【VCAM】[toast]" + ee); } } need_stop = 1; } int finalNeed_stop = need_stop; } private void process_camera2Session_callback(CameraCaptureSession.StateCallback callback_calss){ if (callback_calss == null){ return; } XposedBridge.log("【VCAM】process_camera2Session_callback :" + callback_calss.toString()); XposedHelpers.findAndHookMethod(callback_calss.getClass(), "onConfigureFailed", CameraCaptureSession.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("【VCAM】onConfigureFailed :" + param.args[0].toString()); } }); XposedHelpers.findAndHookMethod(callback_calss.getClass(), "onConfigured", CameraCaptureSession.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log("【VCAM】onConfigured :" + param.args.length); CameraCaptureSession aaa = (CameraCaptureSession)param.args[0]; XposedBridge.log("【VCAM】onConfigured :" + param.args[0].toString()); } }); // XposedHelpers.findAndHookMethod( callback_calss.getClass(), "onClosed", CameraCaptureSession.class, new XC_MethodHook() { // @Override // protected void beforeHookedMethod(MethodHookParam param) throws Throwable { // XposedBridge.log("【VCAM】onClosed :"+ param.args[0].toString()); // } // }); } // 强制重启相机方法 private void forceRestartCamera(XC_LoadPackage.LoadPackageParam lpparam) { try { // 1. 关闭当前相机会话 if (c2_state_cb != null) { XposedBridge.log("【VCAM】断开相机链接 onDisconnected"); Method onDisconnected = c2_state_callback.getMethod("onDisconnected", CameraDevice.class); onDisconnected.invoke(c2_state_cb, (Object)null); } // 2. 重建虚拟Surface recreateVirtualSurface(); // 3. 模拟重新打开相机 XposedBridge.log("【VCAM】准备重启相机 openCamera"); if(c2_state_callback !=null){ XposedBridge.log("【VCAM】c2_state_callback " + c2_state_callback.getClass().getName().toString()); } process_camera2_init(c2_state_callback); process_camera2_play(); XposedBridge.log("【VCAM】强制重启相机成功"); } catch (Exception e) { XposedBridge.log("【VCAM】强制重启相机失败: " + e.toString()); } } //以下代码来源:https://blog.csdn.net/jacke121/article/details/73888732 private Bitmap getBMP(String file) throws Throwable { return BitmapFactory.decodeFile(file); } private static byte[] rgb2YCbCr420(int[] pixels, int width, int height) { int len = width * height; // yuv格式数组大小,y亮度占len长度,u,v各占len/4长度。 byte[] yuv = new byte[len * 3 / 2]; int y, u, v; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int rgb = (pixels[i * width + j]) & 0x00FFFFFF; int r = rgb & 0xFF; int g = (rgb >> 8) & 0xFF; int b = (rgb >> 16) & 0xFF; // 套用公式 y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16; u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128; v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128; y = y < 16 ? 16 : (Math.min(y, 255)); u = u < 0 ? 0 : (Math.min(u, 255)); v = v < 0 ? 0 : (Math.min(v, 255)); // 赋值 yuv[i * width + j] = (byte) y; yuv[len + (i >> 1) * width + (j & ~1)] = (byte) u; yuv[len + +(i >> 1) * width + (j & ~1) + 1] = (byte) v; } } return yuv; } private static byte[] getYUVByBitmap(Bitmap bitmap) { if (bitmap == null) { return null; } int width = bitmap.getWidth(); int height = bitmap.getHeight(); int size = width * height; int[] pixels = new int[size]; bitmap.getPixels(pixels, 0, width, 0, 0, width, height); return rgb2YCbCr420(pixels, width, height); } } package com.example.vcam; import android.media.MediaPlayer; import android.view.Surface; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import de.robv.android.xposed.XposedBridge; //VideoSourceManager import android.media.MediaPlayer; import android.view.Surface; import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import de.robv.android.xposed.XposedBridge; public class VideoSourceManager { private static volatile VideoSourceManager instance; final Map<String, VideoSource> videoSources = new ConcurrentHashMap<>(); private String currentSourceId; private Surface currentSurface; private boolean surfacePrepared = false; private boolean isCameraRestarting = false; public static VideoSourceManager getInstance() { if (instance == null) { synchronized (VideoSourceManager.class) { if (instance == null) { instance = new VideoSourceManager(); } } } return instance; } public static class VideoSource { public final String id; public final String path; public MediaPlayer player; public VideoToFrames decoder; public boolean isInitialized = false; public boolean needsInitialization = false; public boolean isActive = false; public VideoSource(String id, String path) { this.id = id; this.path = path; } public void initialize(Surface surface) { // 如果已使用相同Surface初始化则跳过 if (isInitialized && !needsInitialization) { return; } XposedBridge.log("初始化视频源: " + id + ", Surface: " + surface); // 释放旧资源 releaseResources(); try { // 初始化播放器 player = new MediaPlayer(); player.setDataSource(path); player.setSurface(surface); player.setLooping(true); player.setVolume(0, 0); player.setOnPreparedListener(mp -> { isActive = true; mp.start(); XposedBridge.log("视频源 " + id + " 开始播放"); }); player.setOnErrorListener((mp, what, extra) -> { XposedBridge.log("播放错误: " + what + ", extra: " + extra); return true; }); player.prepareAsync(); // 初始化解码器 decoder = new VideoToFrames(); decoder.set_surfcae(surface); decoder.setSaveFrames("null", OutputImageFormat.NV21); decoder.decode(this.path); isInitialized = true; needsInitialization = false; } catch (Throwable e) { XposedBridge.log("初始化失败: " + e.getMessage()); } } public void releaseResources() { if (player != null) { if (player.isPlaying()) { player.stop(); } player.release(); player = null; XposedBridge.log("释放播放器资源: " + id); } if (decoder != null) { decoder.stopDecode(); decoder = null; XposedBridge.log("释放解码器资源: " + id); } isInitialized = false; isActive = false; } } public void addVideoSource(String id, String path) { if (!videoSources.containsKey(id)) { videoSources.put(id, new VideoSource(id, path)); XposedBridge.log("添加视频源: " + id + ", 路径: " + path); } } public void setCurrentSource(String id) { currentSourceId = id; } public VideoSource getCurrentSource() { return videoSources.get(currentSourceId); } public void prepareForSurface(Surface surface) { // 避免在相机重启过程中处理 if (isCameraRestarting) { XposedBridge.log("相机重启中,跳过Surface准备"); return; } if (surface == null || !surface.isValid()) { XposedBridge.log("无效的Surface,跳过准备"); return; } this.currentSurface = surface; this.surfacePrepared = true; XposedBridge.log("Surface准备就绪: " + surface); VideoSource source = getCurrentSource(); if (source != null) { if (source.needsInitialization) { source.initialize(surface); } else if (source.isInitialized && !source.isActive) { // 如果已初始化但未激活,恢复播放 if (source.player != null && !source.player.isPlaying()) { source.player.start(); source.isActive = true; } } } } public void switchToSource(String sourceId) { XposedBridge.log("切换到视频源: " + sourceId); VideoSource newSource = videoSources.get(sourceId); if (newSource == null) { XposedBridge.log("视频源不存在: " + sourceId); return; } // 暂停当前源 VideoSource current = getCurrentSource(); if (current != null) { if (current.player != null && current.player.isPlaying()) { current.player.pause(); } current.isActive = false; } // 设置新源 currentSourceId = sourceId; // 如果Surface已准备,立即初始化 if (surfacePrepared && currentSurface != null && currentSurface.isValid()) { newSource.initialize(currentSurface); } else { // 标记需要初始化,等待Surface准备 newSource.needsInitialization = true; } } public void onCameraRestart() { XposedBridge.log("相机重启事件"); isCameraRestarting = true; // 暂停所有视频源 for (VideoSource source : videoSources.values()) { if (source.player != null && source.player.isPlaying()) { source.player.pause(); } source.isActive = false; // 标记需要重新初始化 source.needsInitialization = true; } // 重置Surface状态 currentSurface = null; surfacePrepared = false; isCameraRestarting = false; } public void resumePlayback() { VideoSource source = getCurrentSource(); if (source != null && source.isInitialized && !source.isActive) { if (source.player != null && !source.player.isPlaying()) { source.player.start(); source.isActive = true; } } } } 在不重启相机的情况下,如何切换视频源

/* * motor.c * * Created on: Jul 19, 2025 * Author: HONOR */ #include"motor.h" static pid_typedef pid_motor_l;//左电机pid初始化 static pid_typedef pid_motor_r;//右电机pid初始化 //= //初始化左右电机调速系统 // void motor_init(void) { pid_init(&pid_motor_l,0.5,7,0,+100.0f,-100.0f);//左电机初始化 //pid_limitconfig(&pid_motor_l,+8.4f,-8.4f); pid_init(&pid_motor_r,0.5,7,0,+100.0f,-100.0f);//右电机初始化 //pid_limitconfig(&pid_motor_r,+8.4f,-8.4f); } // //电机调速系统进程函数 // void motor_proc(void) { periodic(1)//每间隔1ms执行一次 //#1.获取左右电机的角速度,单位:弧度每秒 float omega_l=encoder_getspeed_l(); float omega_r=encoder_getspeed_r(); //#2.计算pid的输出 float ua_l= pid_compute(&pid_motor_l, omega_l); float ua_r= pid_compute(&pid_motor_r, omega_r); //#3.将电压设置到电机两端,因为模型是输入电压卷积电机系统得到输出转速 //电压占空比 // //float vbat=bat_get(); float duty_l=ua_l ; ///vbat*100.0f; float duty_r=ua_r ; ///vbat*100.0f; pwm_set_l(duty_l); pwm_set_r(duty_r); } // //设置左电机转速的值 //参数:omega为目标值 //单位:弧度每秒 void motor_setomega_l(float omega) { pid_changesp(&pid_motor_l, omega); } // //设置右电机转速的值 //参数:omega为目标值 //单位:弧度每秒 void motor_setomega_r(float omega) { pid_changesp(&pid_motor_r, omega); } // //开关电机 //参数:on,为0时关闭 void motor_cmd(uint8_t on) { pwm_cmd(on); //控制pwm信号 pid_reset(&pid_motor_l);//复位左电机 pid_reset(&pid_motor_r);//复位右电机 } /* * pid.c * * Created on: Jul 19, 2025 * Author:NHY * #1.声明一个pid_typedef的变量 * #2.初始化变量pid_init * #3.计算 * #4.注意每次启动时记得复位。pid_set */ #include"pid.h" // //对kp,ki,kd,输出上下限进行初始化 // void pid_init(pid_typedef*pid,float kp,float ki,float kd,float upper,float low) { pid->kp=kp; pid->ki=ki; pid->kd=kd; pid->t_k_1=0; pid->err_k_1=0.0f; pid->err_int_k_1=0.0f; pid->up_limit=upper; pid->low_limit=low; // //后续可自行更改 // pid->up_limit=+3.4e+38f; //该值为float类型最大值,及假设初始时pid输出上线无穷大 // pid->low_limit=-3.4e+38f;//该值为float类型最小值,及假设初始时pid输出下线无穷小 } // //设置电机pid输出上下限 //参数:upper输出上限,low输出下限 //void pid_limitconfig(pid_typedef*pid,float upper,float low) //{ // pid->up_limit=upper; // pid->low_limit=low; //} // //对设定值进行更改 // void pid_changesp(pid_typedef*pid,float sp) { pid->sp=sp; } // //执行一次pid运算 //参数:fb传感器反馈值,如电机的实际转速 //返回值:co,pid控制器运算的结果 float pid_compute(pid_typedef*pid,float fb) { float err=pid->sp-fb;//计算误差 uint64_t t_k=Getus(); float deltat=(t_k-pid->t_k_1)*1.0e-6;//微秒转秒,获取时间间隔 //首次运行判断 //首次运行时,因为不存在历史数据,计算的值可能不对,故首次是积分项,微分项应该为零 //首次运行时t_k_1=0; float err_dev=0.0f; float err_int=0.0f; if(pid->t_k_1!=0) { err_dev=(err-pid->err_k_1)/deltat;//微分值 err_int=(pid->err_int_k_1+err)*deltat*0.5f+pid->err_int_k_1;//积分值 } float cop=pid->kp*err;//比例项计算值 float coi=pid->ki*err_int;//积分项计算值 float cod=pid->kd*err_dev;//微分项计算值 float co=coi+cop+cod; //pid计算总结果 //更新数据 pid->t_k_1=t_k; pid->err_k_1=err; pid->err_int_k_1=err_int; //输出限幅 if(co>pid->up_limit) co=pid->up_limit; //输出大于上限时,输出上限 if(colow_limit) co=pid->low_limit;//输出小于下限时,输出下限 //积分限幅 if(pid->err_int_k_1>pid->up_limit) pid->err_int_k_1=pid->up_limit;//如果本次的积分值超过上限,则下一次的积分值限制在了上限 if(pid->err_int_k_1low_limit) pid->err_int_k_1=pid->low_limit;//如果本次的积分值低于下限,则下一次的积分值限制在了下限 return co; } // //对pid控制器进行清零,防止前几次的数据干扰 //参数:pid指针 void pid_reset(pid_typedef*pid) { pid->t_k_1=0.0f; //t[k-1],上一次的t值 pid->err_k_1=0.0f; //上一次err[k-1]的值 pid->err_int_k_1=0.0f; //上一次的积分值,err_int[k-1] } /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * *
© Copyright (c) 2025 STMicroelectronics. * All rights reserved.
* * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include"button.h" #include"pwm.h" #include"encoder.h" #include"my_usart.h" #include"motor.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM1_Init(); MX_TIM2_Init(); MX_USART2_UART_Init(); /* USER CODE BEGIN 2 */ pwm_init(); motor_init(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { button_proc(); usart_proc(); motor_proc(); float sp=(HAL_GetTick()/1000)%10*2.0f; motor_setomega_l(sp); motor_setomega_l(sp); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 为什么小车没有按设定值运行

最新推荐

recommend-type

Pansophica开源项目:智能Web搜索代理的探索

Pansophica开源项目是一个相对较新且具有创新性的智能Web搜索代理,它突破了传统搜索引擎的界限,提供了一种全新的交互方式。首先,我们来探讨“智能Web搜索代理”这一概念。智能Web搜索代理是一个软件程序或服务,它可以根据用户的查询自动执行Web搜索,并尝试根据用户的兴趣、历史搜索记录或其他输入来提供个性化的搜索结果。 Pansophica所代表的不仅仅是搜索结果的展示,它还强调了一个交互式的体验,在动态和交互式虚拟现实中呈现搜索结果。这种呈现方式与现有的搜索体验有着根本的不同。目前的搜索引擎,如Google、Bing和Baidu等,多以静态文本和链接列表的形式展示结果。而Pansophica通过提供一个虚拟现实环境,使得搜索者可以“扭转”视角,进行“飞行”探索,以及“弹网”来浏览不同的内容。这种多维度的交互方式使得信息的浏览变得更加快速和直观,有望改变用户与网络信息互动的方式。 接着,我们关注Pansophica的“开源”属性。所谓开源,指的是软件的源代码可以被公众获取,任何个人或组织都可以自由地使用、学习、修改和分发这些代码。开源软件通常由社区进行开发和维护,这样的模式鼓励了协作创新并减少了重复性劳动,因为全世界的开发者都可以贡献自己的力量。Pansophica项目作为开源软件,意味着其他开发者可以访问和使用其源代码,进一步改进和扩展其功能,甚至可以为Pansophica构建新的应用或服务。 最后,文件名称“Pansophica-src-1.3”表明了我们讨论的特定版本的Pansophica开源代码。数字“1.3”很可能指的是该版本号,表明这是Pansophica项目的第1.3个公开版本。这个版本号对于开发者来说很重要,因为它可以帮助他们追踪更新的进度、比较版本间的差异以及选择最适合其项目的版本。 综合以上信息,Pansophica开源项目不仅在搜索代理领域引入了创新的交互方式,而且通过开源的方式,提供了技术共享和协作的可能性。对于IT行业来说,开源项目是推动技术发展的重要力量,它激发了社区的活力,促进了知识的传播和技术的进步。通过构建一个开源社区,Pansophica可以吸引来自世界各地的开发者和研究人员,共同探索如何将搜索技术与交互式虚拟现实技术结合起来,为用户带来更加丰富和有效的信息检索体验。同时,Pansophica的开源性质也使其更容易适应未来技术的发展,随着社区的不断贡献和反馈,这一平台有望在功能和性能上得到持续的优化和增强。
recommend-type

跨平台内容提取无忧:coze工作流应对社交媒体挑战

# 1. 社交媒体内容提取的必要性与挑战 ## 1.1 内容提取的必要性 在数字时代,社交媒体内容是信息与数据流动的主干道,公司、个人和研究者都在寻求从这些信息中提取价值。无论是为了市场趋势分析、品牌监控、消费者洞察还是公共舆论监测,有效的社交媒体内容提取变得至关重要。这不仅有助于企业做出数据驱动的决策,也能使个人更好地理
recommend-type

vrrp主设备发送的免费arp

<think>好的,我现在需要回答用户关于VRRP主设备发送免费ARP的目的和工作原理的问题。首先,我得回忆一下VRRP的基本概念和工作机制。VRRP,虚拟路由冗余协议,主要用于在局域网中提供默认网关的冗余备份,确保网络的高可用性。主设备(Master)负责转发流量,而备用设备(Backup)则在主设备故障时接管工作。 用户的问题集中在主设备发送免费ARP的目的和机制上。根据引用[2],免费ARP用于通知下游设备虚拟MAC地址的变更。当主设备被选举出来后,它需要让局域网内的其他设备知道虚拟IP对应的MAC地址已经指向自己,这样流量才会被正确路由到主设备。免费ARP的作用应该就是更新这些设备的
recommend-type

为Ghost博客平台打造的Meteor流星包装使用指南

从给定文件信息中,我们可以提炼出以下IT知识点: ### 标题知识点:流星Ghost软件包 1. **流星Ghost软件包的用途**:流星Ghost软件包是专为Ghost博客平台设计的流星(Meteor)应用程序。流星是一个开源的全栈JavaScript平台,用于开发高性能和易于编写的Web应用程序。Ghost是一个开源博客平台,它提供了一个简单且专业的写作环境。 2. **软件包的作用**:流星Ghost软件包允许用户在流星平台上轻松集成Ghost博客。这样做的好处是可以利用流星的实时特性以及易于开发和部署的应用程序框架,同时还能享受到Ghost博客系统的便利和美观。 ### 描述知识点:流星Ghost软件包的使用方法 1. **软件包安装方式**:用户可以通过流星的命令行工具添加名为`mrt:ghost`的软件包。`mrt`是流星的一个命令行工具,用于添加、管理以及配置软件包。 2. **初始化Ghost服务器**:描述中提供了如何在服务器启动时运行Ghost的基本代码示例。这段代码使用了JavaScript的Promise异步操作,`ghost().then(function (ghostServer) {...})`这行代码表示当Ghost服务器初始化完成后,会在Promise的回调函数中提供一个Ghost服务器实例。 3. **配置Ghost博客**:在`then`方法中,首先会获取到Ghost服务器的配置对象`config`,用户可以在此处进行自定义设置,例如修改主题、配置等。 4. **启动Ghost服务器**:在配置完成之后,通过调用`ghostServer.start()`来启动Ghost服务,使其能够处理博客相关的请求。 5. **Web浏览器导航**:一旦流星服务器启动并运行,用户便可以通过Web浏览器访问Ghost博客平台。 ### 标签知识点:JavaScript 1. **JavaScript作为流星Ghost软件包的开发语言**:标签指出流星Ghost软件包是使用JavaScript语言开发的。JavaScript是一种在浏览器端广泛使用的脚本语言,它也是流星平台的基础编程语言。 2. **流星和Ghost共同使用的语言**:JavaScript同样也是Ghost博客平台的开发语言。这表明流星Ghost软件包可以无缝集成,因为底层技术栈相同。 ### 压缩包子文件的文件名称列表知识点:meteor-ghost-master 1. **版本控制和软件包结构**:文件名称`meteor-ghost-master`暗示了该软件包可能托管在像GitHub这样的版本控制系统上。文件名中的`master`通常指的是主分支或主版本。 2. **软件包的目录结构**:通过文件名称可以推断出该软件包可能拥有一个标准的流星软件包结构,包含了初始化、配置、运行等必要的模块和文件。 3. **软件包的维护状态**:由于文件名没有包含特定的版本号,我们无法直接得知软件包的最新更新情况。通常,软件包维护者会将最新的版本代码放在`master`分支上。 ### 总结 流星Ghost软件包提供了一个有效的解决方案,使得流星平台的开发者能够在他们的应用中添加Ghost博客功能。软件包的使用简便,通过流星的命令行工具安装,并通过JavaScript代码配置和启动Ghost服务。通过流星Ghost软件包,开发者能够享受流星的实时特性以及Ghost博客系统的便利性。此外,软件包的命名和结构也暗示了其维护和版本控制的模式,有助于开发者更好地理解如何使用和维护这一软件包。
recommend-type

抖音标题生成自动化:用coze工作流释放创意

# 1. 抖音标题生成自动化的重要性 随着社交媒体平台的崛起,内容的吸引力很大程度上取决于标题的创意与精准性。抖音作为一个日活亿级的短视频平台,高质量的标题能够有效提高视频的点击率,增加内容的传播。但是,人工撰写标题不仅耗时耗力,而且很难做到快速响应热点,自动化标题生成工具应运而生。coze工作流,作为一种实现自动化生成抖音标题的工具,其重要性不言而喻。它能够利用大数据分析和机器学习技术,提高标题的吸引
recommend-type

spss消费结构因子分析

<think>好的,我现在需要帮助用户在SPSS中进行消费结构的因子分析。首先,我要回忆一下因子分析的基本步骤和SPSS的操作流程。用户可能对SPSS不太熟悉,所以步骤要详细,同时需要结合他们提供的引用内容,特别是引用[2]中的适用条件和检验方法。 首先,用户提到了消费结构的数据,这可能包括多个变量,如食品、住房、交通等支出。因子分析适用于这种情况,可以降维并找出潜在因子。根据引用[2],需要检查样本量是否足够,变量间是否有相关性,以及KMO和Bartlett检验的结果。 接下来,我需要按照步骤组织回答:数据准备、适用性检验、因子提取、因子旋转、命名解释、计算得分。每个步骤都要简明扼要,说
recommend-type

OpenMediaVault的Docker映像:快速部署与管理指南

根据提供的文件信息,我们将详细讨论与标题和描述中提及的Docker、OpenMediaVault以及如何部署OpenMediaVault的Docker镜像相关的一系列知识点。 首先,Docker是一个开源的应用容器引擎,允许开发者打包应用及其依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。 OpenMediaVault是一个基于Debian的NAS(网络附加存储)解决方案。它专为家庭或小型办公室提供文件共享、网络附加存储以及打印服务。它提供了一个易用的Web界面,通过这个界面用户可以管理服务器配置、网络设置、用户权限、文件服务等。 在描述中提到了一些Docker命令行操作: 1. `git clone`:用于克隆仓库到本地,这里的仓库指的是“docker-images-openmedivault”。 2. `docker build -t omv`:这是一个构建Docker镜像的命令,其中`-t`参数用于标记镜像名称和标签,这里是标记为“omv”。 3. `docker run`:运行一个容器实例,`-t`参数用于分配一个伪终端,`-i`参数用于交互式操作,`-p 80:80`则是将容器的80端口映射到宿主机的80端口。 启动服务的部分涉及OpenMediaVault的配置和初始化: - ssh服务:用于远程登录到服务器的协议。 - php5-fpm:是PHP的一个FastCGI实现,用于加速PHP的运行。 - nginx:是一个高性能的HTTP和反向代理服务器,常用于优化静态内容的分发。 - openmediavault引擎:指的是OpenMediaVault的核心服务。 - rrdcached:用于收集和缓存性能数据,这些数据可以被rrdtool图形化工具读取。 - collectd:是一个守护进程,用于收集系统性能和提供各种存储方式和传输方式来存储所收集的数据。 为了访问服务,需要在浏览器中输入"http:// IP_OF_DOCKER",其中`IP_OF_DOCKER`指的是运行Docker容器的主机IP地址。 描述中还提到了一个步骤:“在System-> Network-> Interfaces中添加带有dhcp的eth0”,这指的是需要在OpenMediaVault的Web管理界面中配置网络接口。`eth0`是网络接口的名称,通常代表第一个以太网接口。DHCP(动态主机配置协议)是一种自动为网络中的设备分配IP地址的协议,这样设备就可以连接网络并开始通信,无需手动配置IP地址。 【压缩包子文件的文件名称列表】中的“docker-images-openmediavault-master”暗示了这是一个包含Docker镜像文件的代码仓库。通常,“master”分支是代码的主分支,包含了代码库中最新且通常是最稳定的版本。用户可以通过克隆该仓库到本地来获取所有相关的Dockerfile、配置脚本及依赖文件,以便能够自行构建和运行OpenMediaVault的Docker镜像。 综上所述,这些知识点涵盖了从基本的Docker概念、Docker命令行操作、OpenMediaVault服务启动和管理,到具体的网络配置及Docker仓库操作,都是进行Docker化OpenMediaVault部署的关键步骤。
recommend-type

小红书文案提取一步到位:coze工作流操作全攻略

# 1. coze工作流概述 工作流系统是企业信息化和数字化转型的核心组件之一,它通过自动化流程管理提升效率,确保业务流程的顺畅执行。coze工作流作为当前市场上较为先进的工作流解决方案,它不仅仅是一套软件工具,更是一个集成化的平台,旨在通过流程自动化和智能化提升企业运营效率。 coze工作流的引入不仅有助于标准化和优化企业的业务流程,还可以通过可配置的流程设计,满足不同部门的特定需求。在组织的业务流程中
recommend-type

戴尔R630设置来电自动开机

<think>嗯,用户需要设置Dell R630服务器在断电恢复后自动开机。这个问题很实用,特别是对于托管在机房或需要远程管理的服务器来说,电源恢复后自动启动能减少运维压力。 从用户提到的R630型号来看,这是Dell PowerEdge系列的主流机型,设置方法应该和其他同代服务器类似。用户可能遇到意外断电后需要手动开机的情况,这会影响服务可用性。 我回忆Dell服务器的电源管理逻辑:主要有两个关键设置点。首先是BIOS里的电源恢复策略,选项包括"保持关机"、"自动开机"和"恢复断电前状态"。其次是iDRAC远程管理卡里的设置,这个更灵活但需要配置网络。 用户可能不熟悉服务器管理,所以需
recommend-type

React-Glide:掌握React轻量级多用途轮播模块

React-glide是一个专为React框架设计的内置多用途轮播模块,它允许开发者在网页中轻松地实现图片或内容的轮播效果。轮播图是一种常见的网页元素,常用于展示一系列的图片或内容,以轮动的方式切换显示,以达到吸引用户注意和提供信息的功能。 首先,需要了解React框架。React是由Facebook开发的一个用于构建用户界面的JavaScript库,它遵循组件化思想,能够将复杂的应用分解成小型的、独立的、可复用的组件。React-glide正是建立在React组件化的基础上,提供了一个轻量级且功能丰富的轮播组件。 安装React-glide非常简单,可以通过npm(Node Package Manager)这个包管理器进行安装。npm是目前流行的JavaScript包管理工具,它能够帮助开发者快速找到合适的库,管理项目依赖,并且能够方便地进行版本控制。安装命令为: ```bash $ npm install react-glide ``` 安装完成后,开发者可以将react-glide作为一个依赖模块引入到React项目中。在组件页面顶部导入模块时,需要同时导入Glide组件以及对应的样式文件。在React中,导入组件和样式的语句如下: ```javascript import { Glide } from 'react-glide'; import 'react-glide/lib/reactGlide.css'; ``` 在使用时,Glide组件充当一个包装器,它能够包裹任何类型的元素。通常,轮播组件中会包含多个图片元素,Glide会自动管理这些图片的显示逻辑。例如,以下是一个基本的使用示例: ```jsx < Glide > < img src = 'http://path/to/image/url' /> < img src = 'http://path/to/image/url2' /> < img src = 'http://path/to/image/url3' /> < /Glide > ``` 在上述代码中,`<Glide>`标签内可以添加任意数量的子元素(通常是`<img>`标签),而Glide组件则会负责这些子元素的轮播展示。 react-glide的轮播组件也支持自定义配置选项,以满足不同场景下的需求。这些选项可以作为属性传递给Glide组件。例如,你可以设置轮播的自动播放间隔、切换动画效果、轮播方向等。具体的属性配置方法需要查阅react-glide的文档。 另外,提到的“种类”和“interface GlideProps”表明react-glide支持TypeScript。TypeScript是JavaScript的一个超集,它在JavaScript的基础上添加了类型系统和对ES6+的新特性的支持。TypeScript最终会被编译成JavaScript代码。使用TypeScript的优势在于能够在开发阶段就发现类型相关的错误,提升代码的健壮性和可维护性。而`GlideProps`可能是指Glide组件可以接收的属性接口,具体如何使用,需要结合TypeScript的类型定义和接口特性来确定。 最后,提到的“压缩包子文件的文件名称列表”中,`react-glide-master`很可能是压缩包的名称。在项目构建和发布过程中,通常会将项目文件打包成一个或多个压缩文件,以便于传输和部署。这种命名方式表明这个压缩文件中包含的是react-glide项目的主分支(master branch)的源代码。 综上所述,react-glide作为一个专为React框架设计的轮播组件,极大地简化了轮播功能的实现过程。开发者只需要通过简单的配置和少量的代码,就可以在React应用中实现美观且功能丰富的轮播效果。无论是用于图片展示、内容更新、引导教程还是广告轮播,react-glide都是一个不错的选择。